android WebView加载优化——拦截替换加载本地资源文件

这个版本有个需求就是优化webview的加载速度,争取做到h5秒开。于是各种找解决方案:
1、美团WebView性能、体验分析与优化
https://tech.meituan.com/WebViewPerf.html
我使用的方法也是参考美团的一点,并没有美团优化的全面
2、腾讯开源框架VasSonic
https://segmentfault.com/a/1190000010711024
QQ使用h5秒开方案,下载尝鲜了下,确实快了很多。但是使用成本太大了,需要后台和前端配合使用,于是就放弃了。

因为我们app图片展示较多,根据app特性我们最后总结的一个简单可行的优化方案是:拦截替换webview中加载的资源文件,替换成事先下载好在本地的文件。这样就不需要去网上加载资源文件了。
好了,上代码:

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        Uri uri = Uri.parse(url);
        if (interceptRequest(uri) != null){
            return interceptRequest(uri);
        }
        return super.shouldInterceptRequest(view, url);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        Uri uri = request.getUrl();
        if (interceptRequest(uri) != null){
            return interceptRequest(uri);
        }
        return super.shouldInterceptRequest(view, request);
    }

在需要连网加载资源的地方做拦截,判断本地是否有已经下载好的文件,如果有就加载本地文件,否则就网络加载。

/**
     * 拦截url 判断本地是否有缓存资源文件
     * @param uri
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private WebResourceResponse interceptRequest(Uri uri){
        WebResourceResponse resourceResponse = null;
        for (int i = 0; i < mKeyList.size(); i++) {
            //判断是否要加载本地资源
            if (mKeyList.get(i).contains(uri.getAuthority())) {
                try {
                    //加载资源类型
                    String mimeType = "";
                    if (uri.getPath().contains(".js")) {
                        mimeType = "text/javascript";
                    } else {
                        mimeType = MimeTypeMapUtils.getMimeTypeFromUrl(uri.toString());
                    }
                    String path = FilePath.OfflineCache + uri.getAuthority() + uri.getPath();
                    if (!TextUtils.isEmpty(mimeType)) {
                        resourceResponse =  new WebResourceResponse(mimeType, "", 200, "ok", header, new FileInputStream(path));
                        return resourceResponse;
                    }
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
        return resourceResponse;
    }

mKeyList是事先缓存在本地key

 private List<String> mKeyList;
  MOfflineCacheBean cacheBean = SPUtils.get(Cosmeapp.mCosmeapp, SPUtils.S_K_OFFLINE, MOfflineCacheBean.class);
        mKeyList = cacheBean.getOfflineList();

MimeTypeMapUtils资源类型判断

public class MimeTypeMapUtils {

    public static String getFileExtensionFromUrl(String url) {
        url = url.toLowerCase();
        if (!TextUtils.isEmpty(url)) {
            int fragment = url.lastIndexOf('#');
            if (fragment > 0) {
                url = url.substring(0, fragment);
            }

            int query = url.lastIndexOf('?');
            if (query > 0) {
                url = url.substring(0, query);
            }

            int filenamePos = url.lastIndexOf('/');
            String filename =
                    0 <= filenamePos ? url.substring(filenamePos + 1) : url;

            // if the filename contains special characters, we don't
            // consider it valid for our matching purposes:
            if (!filename.isEmpty()) {
                int dotPos = filename.lastIndexOf('.');
                if (0 <= dotPos) {
                    return filename.substring(dotPos + 1);
                }
            }
        }

        return "";
    }
    public static String getMimeTypeFromUrl(String url) {
        return  MimeTypeMap.getSingleton().getMimeTypeFromExtension(getFileExtensionFromUrl(url));
    }
    public static String getMimeTypeFromExtension(String extension) {
        return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
    }
}

这里要说一下这个替换方法:

resourceResponse =  new WebResourceResponse(mimeType, "", 200, "ok", header, new FileInputStream(path));

构造方法,见名知意原则。

WebResourceResponse(String mimeType, String encoding, int statusCode, String reasonPhrase, Map<String, String> responseHeaders, InputStream data)

第一就是这个reasonPhrase最好用英文字母,我之前用的汉字,他们解析不出来。
第二就是responseHeaders

 header.put("Access-Control-Allow-Origin", "*");
        header.put("Access-Control-Allow-Headers", "Content-Type");

好了,在我们这种图片比较多的app中,使用这种优化,webview打开速度提升还是挺大的,肉眼可见啊。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值