Android WebView性能优化(一)

一、简介:

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

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

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

优就业Android教程-WebView优化之路

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

优就业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 内存泄漏的问题便得以解决。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,378评论 25 709
  • 被文同时发布在CSDN上,欢迎查看。 APP内存的使用,是评价一款应用性能高低的一个重要指标。虽然现在智能手机的内...
    大圣代阅读 10,274评论 2 54
  • 企业级市场以及存在了很多年,但一直不温不火,尤其跟中国消费互联网过去十年比起来还相差很远。但在中国,过去一两年,S...
    策略书生阅读 1,488评论 0 0
  • 当我停下在试卷上划动着的笔,我明白我已经走过了青春的一半旅程;当我们的语文作文题目从《童年》变成《青春》,我知道那...
    青衫微雪阅读 4,681评论 1 3
  • 熬夜已经不是什么新鲜的话题了,但是,颜值也算横行霸道的抢占了人生的头条啊,脸那么重要,大家是都不要了么? 1。初心...
    核桃仙子儿阅读 4,635评论 2 2