内存泄漏--webview

In Android app development, webview is widely used. However, if you are using webview without caution, it will easily consume a lot of memory. And your app may even crash due to insufficient memory.

The memory issue of webview is well-known, here are two great links about the issue.

Post in English

Post in Chinese

For Android 4.4 and above, Android is using chromium as the core of webview. For Android 3.1 to 4.3, Android is using webkit as the core of webview. Most of the memory leak happens on webkit.

And the blog will briefly summarize the tips to prevent webview memory leak

Tip 1: When clearing the webview reference. Simply set it to null is not enough.webview.destroy()must be called. Example code:

123456789

@OverridepublicvoidonDestroy(){super.onDestroy();if(webView!=null){webView.removeAllViews();webView.destroy();}webView=null;}

Tip 2: Using application context when initializing webview. This means webview should not be initialized from xml. You need to create it programmatically. Example Code:

123

WebViewwebView=newWebView(getApplicationgContext());LinearLayoutlinearLayout=findViewById(R.id.xxx);linearLayout.addView(webView);

By doing this, 90% of the time, webview memory consumption is no longer an issue. However, if you want to play a full screen video in your webview, theonShowCustomerViewofWebChromeClientwill be triggered. And beforeonShowCustomerViewis triggered, the Webkit will do some preprocessing. Due to a bug in Webkit’s implementation, a static variable inhtml5videoviewproxywill hold the webview’s reference which will caused a leak and you cannot do much about it.

Another problem using application context is that when your webview wants to popup a window. In webview’s default behaviour, there is a cast fromApplicationContexttoActivityContextwhich will cause your app crash. Of course, you can implement your own method of handling popup to walk around this problem, but it takes a lot of unnecessary effort.

P.S. we can inject javascript into webview to do many tricks. I will later post another blog about using javascript in webview.

Tip 3: I personally did not test this method, but I think the method is creative and instructive so I am noticing it down here.

The main idea is webkit does not provide us a method to release the reference, so let us do it ourself by reflection. The reason why I did not use it is because it highly depends on webkit’s implementation and you have to write different code for different Android versions.

123456789101112131415161718

publicvoidsetConfigCallback(WindowManagerwindowManager){try{Fieldfield=WebView.class.getDeclaredField("mWebViewCore");field=field.getType().getDeclaredField("mBrowserFrame");field=field.getType().getDeclaredField("sConfigCallback");field.setAccessible(true);ObjectconfigCallback=field.get(null);if(null==configCallback){return;}field=field.getType().getDeclaredField("mWindowManager");field.setAccessible(true);field.set(configCallback,windowManager);}catch(Exceptione){}}

Call the method in onCreate and onDestroy

123456789

publicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setConfigCallback((WindowManager)getApplicationContext().getSystemService(Context.WINDOW_SERVICE));}publicvoidonDestroy(){setConfigCallback(null);super.onDestroy();}

Ultimate Tip: This method is the ultimate way to solve the problem and many well-known app such as QQ and Wechat are using it as well.

The idea is to start a separate process for webview and kill the process when existing the webview. The drawback of doing this is that you need to handle interprocess communication carefully. My suggestion is you can create apreProcessProxyandpostProcessProxyto handle IPC and passing information around using intent.

Example code: define webview activity in a separate process

12345

Kill the process when destroying the activity

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

推荐阅读更多精彩内容