问题场景:
公司App业务上曾经利用WebView加载过一个聊天的网页,该网页内容的更新采取的是每隔10s进行一次刷新获取最新的聊天内容,今天在调整相关业务逻辑的时候,后台同学发现客户端一直在访问该聊天网页,但此时App页面已经关闭,这就说明WebView并没有真正的被销毁回收,而是任然存留在App中,占用着手机内存,而且还在执行着网络访问,这样当然是不行的啦,内存泄漏了哎,早就听说WebView存在内存泄漏的问题了,赶紧找找资料解决一下。
问题说明:
WebView是Android中一个比较特殊的View,可以直接加载一个网页,在调用webView.destory()的时候,必须确保webView已经从View Tree中被删除,否则这个函数是不会执行的,而在一般的App中,WebView的用法是在xml中静态定义的WebView,只有在整个View退出后调用webView.destory()才会被正确执行,但当整个view退出后又找不到webView了,layout已经被销毁,无法执行相关的removeView操作,无法移除webView,webView得不到移除,destory方法就无法正常使用,这是个矛盾。
解决方案:
动态添加WebView到布局中,不要在xml中定义WebView。
private LinearLayout layoutContent;
private WebView webView;
private String url;// 网址
private void initWebView() {
// Context尽量用Application的Context,活的长,避免内存泄漏
webView = new WebView(BaseApplication.getContext());
// 设置params,否则WebView显示不出来
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
webView.setLayoutParams(params);
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setAllowFileAccess(true);
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
webView.setWebViewClient(new MyWebViewClient());
webView.loadUrl(url);
layoutContent.addView(webView);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (webView != null) {
LogUtils.d("-----webView != null----->");
// 让WebView加载null内容
webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
webView.clearHistory();
ViewParent parent = webView.getParent();
if (parent != null) {
LogUtils.d("------parent != null----->");
((ViewGroup) parent).removeView(webView);
}
webView.destroy();
webView = null;
}
}
private class MyWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}