美文网首页
webView泄漏

webView泄漏

作者: 主音King | 来源:发表于2018-12-29 13:12 被阅读5次

1、在activity的onDestroy方法中释放:

mWebView.removeAllViews();
mWebView.destroy();
mWebView=null;

是不起作用的。
2、new一个webView(不是在.xml中定义)

mWebView=new WebView(this);
LinearLayout linearLayout  = findViewById(R.id.xxx);
linearLayout.addView(mWebView);
@Override
protected void onDestroy() {
    if( mWebView!=null) {
       mWebView.setVisibility(View.GONE);
       mWebView.removeAllViews();
       mWebView.destroy();
    }
    super.onDestroy();
}

不起作用。
但是用

mWebView=new WebView(getApplicationContext());

可以解决泄漏(不占用activity了),但是在很多情况下会包错,是webview的某些特殊动作产生由Application到Activity的类型转换错误。
所以还是存在问题。
3、手动删除引用

public void setConfigCallback(WindowManager windowManager) {
    try {
        Field field = WebView.class.getDeclaredField("mWebViewCore");
        field = field.getType().getDeclaredField("mBrowserFrame");
        field = field.getType().getDeclaredField("sConfigCallback");
        field.setAccessible(true);
        Object configCallback = field.get(null);

        if (null == configCallback) {
            return;
        }

        field = field.getType().getDeclaredField("mWindowManager");
        field.setAccessible(true);
        field.set(configCallback, windowManager);
    } catch(Exception e) {
    }
}
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setConfigCallback(WindowManager)getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
    }
    @Override
    public void onDestroy() {
        setConfigCallback(null);
        super.onDestroy();
    }

可能部分项目中有用。感觉麻烦,没测过
4、多进程应该可以吧...
5、从根源解决
webview引起的内存泄漏主要是因为org.chromium.android_webview.AwContents 类中注册了component callbacks,但是未正常反注册而导致的。
org.chromium.android_webview.AwContents 类中有这两个方法 onAttachedToWindow 和 onDetachedFromWindow;系统会在attach和detach处进行注册和反注册component callback;
在onDetachedFromWindow() 方法的第一行中:

if (isDestroyed()) return;

isDestroyed() 返回 true ,就不会执行unregister的操作,我们的activity退出的时候,都会主动调用 WebView.destroy() 方法,这会导致 isDestroyed() 返回 true,destroy()的执行时间又在onDetachedFromWindow之前,所以就会导致不能正常进行unregister().
然后解决方法就是:让onDetachedFromWindow先走,在主动调用destroy()之前,把webview从它的parent上面移除掉。

ViewParent parent = mWebView.getParent();
if (parent != null) {
    ((ViewGroup) parent).removeView(mWebView);
}
mWebView.destroy();

完整代码:

@Override
protected void onDestroy() {
    if( mWebView!=null) {
        // 如果先调用destroy()方法,则会命中if (isDestroyed()) return;这一行代码,需要先onDetachedFromWindow(),再
        // destory()
        ViewParent parent = mWebView.getParent();
        if (parent != null) {
            ((ViewGroup) parent).removeView(mWebView);
        }
        mWebView.stopLoading();
        // 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错
        mWebView.getSettings().setJavaScriptEnabled(false);
        mWebView.clearHistory();
        mWebView.clearView();
        mWebView.removeAllViews();
        mWebView.destroy();
    }
    super.on Destroy();
}

相关文章

网友评论

      本文标题:webView泄漏

      本文链接:https://www.haomeiwen.com/subject/aovulqtx.html