100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > android webview 预加载 H5预加载的实现

android webview 预加载 H5预加载的实现

时间:2021-08-27 09:52:12

相关推荐

android webview 预加载 H5预加载的实现

预加载说小了就是个提前load,说大了,就是HybridApp的最基础功能。

Html5官方有个prefetch的attribute,用来做页面间的prefetch。其实在native跳h5容器的过程中更需要这种流程,否则很容易导致体验劣化。

其实方案蛮多的:

直接下载url + WebView#loadDataWithBaseURL

优点是简单,缺点就是只能预加载下个页面的html内容,这样一来,实际效果很差,常常只能预加载1%不到的数据量

用隐藏的WebViewFragment加载,需要时做动画显示

优点也是速度最快,坑就非常多了:

html加载过程完整,控制行为需要在WebChromeClient/WebViewClient做非常多的分支判断

需要兼容动画效果

需要控制back

最重要的,会导致js中的window#onload之类的函数不合理的触发,引发逻辑问题

用WebView提前load,靠WebView的cache

仍然不复杂,因为在预加载时可以禁掉js,真正加载的时候允许js,上一个方案的控制部分就解决了。问题在于,WebView的Cache是一体的,一清全清,一旦需要清理缓存那就会出现各种各样的全局问题了。

用WebView提前load,手写缓存

最复杂的方案,但是目前看没什么坑。

具体来说:

prefetch阶段,重写WebViewClient#onLoadResource,将所有资源都下载到本地

本地缓存的文件结构:用baseUrl#hashCode生成一个文件夹,每一个资源都缓存到baseUrl#hashCode/resourceUrl#hashCode的文件中

缓存过程中,要标记一下,保证未完成的资源不被读取

mime和charset通过HttpURLConnection的content-type来解析

复用阶段,重写WebViewClient#shouldInterceptRequest,重定向所有资源请求到本地stream

清理阶段,交给外部,外部通过baseUrl,或者根目录来清理对应的缓存

上面的思路发现了一个问题:所有预加载的网页会被下载两遍,因为并没有阻断WebView自己的下载。解决这个最好办法就是给WebView加一个proxy,在proxy中存储所有数据。乍看之下,WebView没有Proxy接口,所以网上就奔放了。然而,细想一下,shouldInterceptRequest不就是Proxy吗?只需要在原始的InputStream上wrap一层,在wrapper中做想做的事情就好了。所以最终方案是:

prefetch阶段,重写WebViewClient#shouldInterceptRequest,为每一个请求生成HttpUrlConnection,为得到的InputStream注册一个onValueRead回调,回调中存储读取到的数据

mime会有不严谨的情况,导致显示错误,解决方法

其他部分和上一个方法一致。

细说起来,还有几个值得改进的地方:

- fat32对于多文件支持很差。所以最好能做自己的资源定位方法

- VasSonic对于流的处理更加细致,可以做一个adapter层,如果文件只下载了一半也能用 - 目前所有的东西都是基于md5,其实改成原始文件路径可能也不错 - 部分资源是可以做预置的,需要的只是在stream的来源上进行区分(File或net)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。