前言:
在客户端开发过程中, 我们难免有一些页面需要配合h5去展示, android中使用webview去加载h5页面, 但是使用h5页面去加载的时候, 明显体验要比原生差很多, 尤其是第一次请求网页时.
这是因为h5页面在加载时, 需要从服务器获取各种资源,比如: 图片, js文件, css文件, 自身api等... 相比而言, 客户端的资源都是静态的, 我们通常只是去请求个自己的api, 用户体验会好很多.
为了解决这个问题, 我们可以采取以下方案:
注意: 这种方法比较适合于一些大型首页, 相当一部分的资源文件如图片和js是不会发生变动的. 不过即使发生变动我们也会有应对策略, 后续会提到~
方案: 客户端将静态资源包预置到apk内, 在webview内进行资源拦截和替换
步骤:
- 将前端需要预先加载资源放置到assert目录中
- 使用webview进行网络资源拦截
- 使用assert下的资源包将resource进行动态替换
代码实现:
mWebView.setWebViewClient(new WebViewClient() {
@Nullable
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
//这里我们拦截资源名包含gjhh-600x400.jpg的请求
if(request.getUrl().toString().contains("gjhh-600x400.jpg")){
// 我先使用本地的一个drawable测试替换, 在实际操作中我们也可以将资源包统一放置assert目录下进行管理
Drawable drawable = getResources().getDrawable(R.drawable.base_app_icon);
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(),
Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());
drawable.draw(canvas);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG,100,baos);
InputStream is = new ByteArrayInputStream(baos.toByteArray());
//使用本地的资源包response
return new WebResourceResponse("image/png","utf-8",is);
}
return super.shouldInterceptRequest(view, request);
}
}
问题: 如果资源需要发生改变, 更新, 怎么办呢?
如果我们没有预置web的这些资源的话, 他们的更新极其容易, 客户端可以撒手不管. 但是当把资源放入到客户端时, 我们应该如何做到及时的更新呢?
有三种解决方案:
1. 客户端发版 (这是最简单粗暴的做法)
客户端更新新的资源文件之后, 发布新版本
2. 采用热更新的方式动态下发新的资源包
为了避免强制升级或者发布新版本后下载不及时问题, 可以采用热更新的方式做资源文件的替换, 大家采用自己喜欢的热更新方式即可
3. 当有资源变更时, 服务器下发资源给客户端, 客户端和服务器需各自持有一个资源的唯一码来用作校验
采用这种方法:
1.首先客户端会持有当前最新的资源包, 以及与服务器约定好的初始资源唯一码;
2.客户端在每次启动的时候, 先去提交给服务器唯一码及资源包名, 由服务器判断当前资源是否为最新, (此处借鉴http缓存处理--Etag对比)
如果是最新则进行将assert下资源解压值指定目录, 当webview请求数据资源时, 从该目录进行匹配替换.
如果不是最新资源, 服务器下发最新的资源包及资源的id等信息, 客户端至相同位置进行覆盖, 保证webview取到最新的资源
在这个处理过程中, 我们还需要考虑资源包会被系统清理删除等问题, 以及资源包下载是否完整等.
以上还未进行实践, 可能有错误之处, 先做笔记后续工作用到会加以改进!
End..








网友评论