Android WebView性能优化(一)

一、简介:

随着app的迭代,嵌入的html5界面越来越多了,Webview这个强大组件引起的问题越发的多起来,例如:
1、WebView导致的oom问题

2、Android版本不同,采用了不同的内核,兼容性crash

3、不同版本实现不同,甚至URI不规范也会引起不同程度的问题

《Android WebView性能优化(一)》 优就业Android教程-WebView优化之路

为了解决以上问题,我们把WebView模块做成独立进程
WebView独立进程Android允许一个app同时存在多个进程,可以根据需要把不同的模块放到不同进程中处理。

《Android WebView性能优化(一)》 优就业Android教程-WebView优化之路

比如微信v2.X+版本的时候把Network部分做轻重进程分离,独立到一个单独的进程(:push)中,而上面两个层级依然跑在微信的主进程(:workder)中。而对于有内存泄露问题的webview或者其他不频繁使用的功能,再把其分离到独立的工具进程(:tools)中。通过分离进程,微信第一次重构解决了系统因为微信资源消耗,主动干掉微信服务的困境。

二、WebView独立进程的好处

1.有效增大App的运存,减少由webview引起的内存泄露对主进程内存的占用。

2.避免WebView的Crash影响App主进程的运行。

3.拥有对WebView独立进程操控权。

弊端:WebView进程与其他进程通讯的方式,把webview独立进程之后会发现,埋点功能和接收主进程数据都不正常了,这里就涉及到进程间通讯的问题了;
进程通讯大概就是这几种,aidl,messager,content provider,广播;

三、webview的配置

下面贴上我自己的配置代码:

ublic class WebViewConfig {

    //初始化WebView配置
    public static void initWebViewConfig(WebView webview) {
        // 设置WebView初始化尺寸,参数为百分比
        webview.setInitialScale(100);
        //设置WebView可触摸放大缩小
        webview.getSettings().setSupportZoom(true);
        webview.getSettings().setBuiltInZoomControls(true);
        //WebView双击变大,再双击后变小,当手动放大后,双击可以恢复到原始大小
        webview.getSettings().setUseWideViewPort(true);
        // 获取WebSettings对象
        WebSettings webSettings = webview.getSettings();
        // 设置WebView支持运行普通的Javascript
        webSettings.setJavaScriptEnabled(true);
        // 设置WebChromeClient,以支持运行特殊的Javascript
        webview.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                return super.onJsAlert(view, url, message, result);
            }
        });
        //(默认)根据cache-control决定是否从网络上取数据。
        webSettings.setCacheMode(LOAD_DEFAULT);
        // 阻止网络图片加載
        webview.getSettings().setBlockNetworkImage(false);
    }

    //销毁资源
    public static void destroy(WebView webview) {
        webview.stopLoading(); //停止加载
        ((ViewGroup) webview.getParent()).removeView(webview); //把webview从视图中移除
        webview.removeAllViews(); //移除webview上子view
        webview.clearCache(true); //清除缓存
        webview.clearHistory(); //清除历史
        webview.destroy(); //销毁webview自身
        //Process.killProcess(Process.myPid()); //杀死WebView所在的进程
    }
}

四、清单文件中,声明一下 process属性
<activity
            android:name=".ui.details.WebViewActivity"
            android:process=":webview"
            android:screenOrientation="portrait" />
总结

Android 中的 WebView 存在很大的兼容性问题,不仅仅是 Android 系统版本的不同对 WebView 产生很大的差异,另外不同的厂商出货的 ROM 里面 WebView 也存在着很大的差异。更严重的是标准的 WebView 存在内存泄露的问题,看这里WebView causes memory leak – leaks the parent Activity。所以通常根治这个问题的办法是为 WebView 开启另外一个进程,通过 AIDL 与主进程进行通信,WebView 所在的进程可以根据业务的需要选择合适的时机进行销毁,从而达到内存的完整释放。

这段话来自胡凯翻译的 Google Android 内存优化之 OOM 。这里提到的让 WebView 独立运行在一个进程里,用完 WebView 后直接销毁这个进程,即使内存泄露了,也不会影响到主进程。微信,手 Q 等 App 也采用了这个方案。但是这就涉及到了跨进程通讯,处理起来就比较麻烦。

2、另外个解决方案,就是使用自己封装的 WebView,比如上面提到的 X5 内核,且使用 WebView 的时候,不在 XML 里面声明,而是在代码中直接 new 出来,传入 application context 来防止 activity 引用被滥用。

WebView webView =  new WebView(getContext().getApplicationContext());
webFrameLayout.addView(webView, 0);

在使用了这个方式后,基本上 90% 的 WebView 内存泄漏的问题便得以解决。

    原文作者:唠嗑008
    原文地址: https://www.jianshu.com/p/c13eb7759c68
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞