html5 webview的本地存储优化

最近接了一个需求,是一个内嵌在webview里的类似于照片墙的页面。可以想见,这样的一个页面在3g甚至是2g的网络环境下,访问速度该面临多大的挑战。利用一些前端优化的技术,最近做了一些尝试,在这里小结一下。

先看一下这样一个页面的组成。一些js,css,若干张图片,还有一个初始化html请求。

首先来说主干流程。为了让用户及早看到内容,我们这样安排页面的加载:

  1. 首先展示上一次看过的图片内容;
  2. 此时,发送ajax请求到服务器,获取最新的图片url们;
  3. 在ajax请求完毕时,加载新的图片。

好,上面是最基本的思路。首先,我们需要让第一个请求,也就是html请求尽快完成,最快的方式也许莫过于保存在本地了。这里,可以使用html5的cache manifest。

<html manifest=’/pic_wall.manifest’>

manifest内部可以这样写:

CACHE MANIFEST
#version 1
/pic_wall.php
/img/web_view/iphone/loading.jpg
/js/jq.mobi.min.js
/js/wv_common.js
/js/backbone_json2_underscore_min.js
/js/pic_wall.js

NETWORK:
*

唯一需要注意的是version这一行,虽然是注释,但是可以用来指定manifest的版本。假设我们修改了其中一个js,需要告诉客户端及时更新,就可以把version改为2。

这样,在一般情况下,使用chrome,safari之类的浏览器就可以测试成功了。但是在iphone 5.1上使用safari测试时,会有一个错误提示,说pic_wall.manifest在下载时的mimetype不正确,是text/plain。 这就要修改http服务器的mime type配置了,把manifest后缀的请求设置为text/cache-manifest类型就可以了。

好,现在我们把目光转向js和css。这俩家伙虽然已经列在了manifest文件中,但是当我们点击浏览器的刷新按钮时,他们仍然会向服务器发起 一次请求,得到一个304后才安心走到下一步。这个现象根据浏览器的实现各有不同,尤其是在android webview下不太可靠。在移动网络环境下,这些304请求也是相当费时的——每次网络连接都会花掉不少时间。怎么消除这些304呢,这个比较简单,以 apache为例,使用一个mod_expires模块,给js和css类型的请求加上etag和max-age就可以了。另外,为了让第一次下载快一 点,还可以设置apache使用gzip encoding来下发。

好了,页面上看得见的就只剩下图片没说了。在这种应用中,图片有时候是动态生成的,比如根据需要裁切的,这就要在图片服务器端加上一些缓存header,比如etag和max-age,来达到浏览器端缓存的目的。

现在,所有的内容都可以缓存在浏览器了,但是,图片不应该是写死在页面上的,它们应当是由页面从服务器请求下来src、然后拼装放在dom里的。这 个规定图片墙组织结构的请求,我们用一个ajax来完成。ajax请求从服务器端下载到一个描述着图片墙内容的json,然后解析成图片的排版结构和图片 src,并拼成dom放到页面上。

好,到此为止,页面已经可以完成流程了。但是,假设我们的图片墙内容是飞速变化的(比如这是一个海量用户正在上传的图片的展示墙),怎么样在用户下一次刷新页面时,让他有个飞速的体验呢?

首先,要让他在刷新或者重新打开页面时,有基本的内容可以先看着,俗话说骑驴找马嘛。我们已经把html请求、js、css缓存在本地了,可是上一 次看过的图片墙结构——那个json字符串没有。这里,我们可以使用html5 的localStorage来保存它:在下载之后,保存到localStorage里;js加载完后,从localStorage读取它并展示出来。用户 就可以看到上一次看过的图片墙了。此时,再发起ajax请求,更新照片墙。

好,到此位置,在电脑的非ie浏览器上,已经可以完成我们的想法了;iphone上也可以;iphone的webview上也可以;但是,唯独android webview上还不行……

android webview需要做如下设置:

        wv.getSettings().setDomStorageEnabled(true);//设置可以使用localStorage
        wv.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);//默认使用缓存
        wv.getSettings().setAppCacheMaxSize(8*1024*1024);//缓存最多可以有8M
        wv.getSettings().setAllowFileAccess(true);//可以读取文件缓存(manifest生效)
        wv.getSettings().setAppCacheEnabled(true);//应用可以有缓存
这样,一般情况下,android webview也没问题了。但是我们遇到一种情况,就是app本身比较大,占用比较多的内存,此时即便有上述设置,在打开上面的图片墙页面时,也会不正 常。我看到的现象是:页面可以加载出来,但是突然会显示手机桌面,1秒钟后又自动切回到app打开图片墙之前的界面。怀疑是内存限制问题,还没有找到确切 答案。
额……没错,我们还没说很重要的一点,就是第一次加载。在加载时,我们尽量让请求数少一点,可以把js和css压缩后铺到html里,反正 html的那个请求以后会有缓存了。再之后就是图片们;因为我们已经请求下来描述图片信息的json数据了,此时可以先把图片墙的轮廓画出来,然后把真实 图片的位置用默认的小图标占上;等到一张图片加载完成时,再替换掉默认小图标,做得炫一点的话,可以模仿flipboard或者zaker那样的翻板效 果。
posted @ 2012-12-07 11:38  坏混混  阅读(1317)  评论(0)    收藏  举报