WebView面試詳解

一、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)注明出處。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容