一、WebView 常見的一些坑
1. webview 在android api16以及之前版本的安全漏洞,該漏洞是因?yàn)槌绦驔]有正確的限制webview.addjavascriptinterface方法,讓遠(yuǎn)程攻擊者可以使用java的反射機(jī)制利用該漏洞執(zhí)行任意的java對(duì)象方法。
2. webview動(dòng)態(tài)添加到其他布局的時(shí)候,在activity銷毀的生命周期時(shí),需要主動(dòng)調(diào)用webview.removeallviews和webview的ondestory方法釋放內(nèi)存,否則會(huì)導(dǎo)致內(nèi)存泄漏。
3. jsbridge ,js橋可以允許遠(yuǎn)程網(wǎng)頁端與android的native端進(jìn)行通信,通俗的說就是使用js橋可以在android代碼中調(diào)用網(wǎng)頁的js方法,也可以讓js調(diào)用原生的代碼
4. webview.onpagefinished方法,該方法并不靠譜,按照api上面的說法,在web頁面完全加載完成的時(shí)候會(huì)回調(diào)該方法,但在實(shí)際應(yīng)用過程中,該方法在跳轉(zhuǎn)url的時(shí)候會(huì)被多次調(diào)用,更加靠譜的方法是使用onprogresschange方法代替該方法的功能,當(dāng)newProgress為100的時(shí)候,即是頁面加載完成。
5. 后臺(tái)耗電問題,webview加載網(wǎng)頁的時(shí)候,會(huì)自動(dòng)創(chuàng)建線程,如果如果使用不當(dāng),這些線程會(huì)永遠(yuǎn)在后臺(tái)運(yùn)行,導(dǎo)致你的應(yīng)用耗電量居高不下,這個(gè)問題的解決方式是在activity的ondetory方法中銷毀webview。
6. webview硬件加速導(dǎo)致渲染問題,比如加載的時(shí)候會(huì)有閃屏現(xiàn)象,解決方式就是暫時(shí)關(guān)閉硬件加速。
7. webview導(dǎo)致內(nèi)存溢出的原因,主要是因?yàn)閮?nèi)部類持有外部類的引用導(dǎo)致外部類無法釋放的問題。
二、關(guān)于webView的內(nèi)存泄漏問題
1、不要在.xml文件中定義webview節(jié)點(diǎn)
2、 從根源解決(劃重點(diǎn))
前面的方法都沒有解決我內(nèi)存泄漏的問題,然后我看到了一篇文章是從源碼角度分析了webview內(nèi)存泄漏的原因,最后按作者的方法解決了問題,后面會(huì)貼上原文地址。這里簡(jiǎn)單說一下:
原文里說的webview引起的內(nèi)存泄漏主要是因?yàn)閛rg.chromium.android_webview.AwContents 類中注冊(cè)了component callbacks,但是未正常反注冊(cè)而導(dǎo)致的。
org.chromium.android_webview.AwContents 類中有這兩個(gè)方法 onAttachedToWindow 和 onDetachedFromWindow;系統(tǒng)會(huì)在attach和detach處進(jìn)行注冊(cè)和反注冊(cè)component callback;
在onDetachedFromWindow() 方法的第一行中:
if (isDestroyed()) return;,
如果 isDestroyed() 返回 true 的話,那么后續(xù)的邏輯就不能正常走到,所以就不會(huì)執(zhí)行unregister的操作;我們的activity退出的時(shí)候,都會(huì)主動(dòng)調(diào)用 WebView.destroy() 方法,這會(huì)導(dǎo)致 isDestroyed() 返回 true;destroy()的執(zhí)行時(shí)間又在onDetachedFromWindow之前,所以就會(huì)導(dǎo)致不能正常進(jìn)行unregister()。
然后解決方法就是:讓onDetachedFromWindow先走,在主動(dòng)調(diào)用destroy()之前,把webview從它的parent上面移除掉。
ViewParent parent = mWebView.getParent();
if (parent != null) {
((ViewGroup) parent).removeView(mWebView);
}
mWebView.destroy();
完整的activity的onDestroy()方法:
@Override
protected void onDestroy() {
if( mWebView!=null) {
// 如果先調(diào)用destroy()方法,則會(huì)命中if (isDestroyed()) return;這一行代碼,需要先onDetachedFromWindow(),再
// destory()
ViewParent parent = mWebView.getParent();
if (parent != null) {
((ViewGroup) parent).removeView(mWebView);
}
mWebView.stopLoading();
// 退出時(shí)調(diào)用此方法,移除綁定的服務(wù),否則某些特定系統(tǒng)會(huì)報(bào)錯(cuò)
mWebView.getSettings().setJavaScriptEnabled(false);
mWebView.clearHistory();
mWebView.clearView();
mWebView.removeAllViews();
mWebView.destroy();
}
super.on Destroy();
}
這個(gè)方法親測(cè)有效。
作者:wencymu
鏈接:http://www.lxweimin.com/p/3e8f7dbb0dc7
來源:簡(jiǎn)書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。