亚洲免费在线视频-亚洲啊v-久久免费精品视频-国产精品va-看片地址-成人在线视频网

您的位置:首頁技術(shù)文章
文章詳情頁

關(guān)于 Android WebView 的內(nèi)存泄露問題

瀏覽:71日期:2022-09-27 11:45:20

在這次開發(fā)過程中,需要用到webview展示一些界面,但是加載的頁面如果有很多圖片就會(huì)發(fā)現(xiàn)內(nèi)存占用暴漲,并且在退出該界面后,即使在包含該webview的Activity的destroy()方法中,使用webview.destroy();webview=null;對(duì)內(nèi)存占回收用還是沒有任何效果。有人說,一旦在你的xml布局中引用了webview甚至沒有使用過,都會(huì)阻礙重新進(jìn)入Application之后對(duì)內(nèi)存的gc。包括使用MapView有時(shí)一會(huì)引發(fā)OOM,幾經(jīng)周折在網(wǎng)上看到各種解決辦法,在這里跟大家分享一下。但是到目前為止還沒有找到根本的解決辦法,網(wǎng)上也有說是sdk的bug。但是不管怎么樣,我們還是需要使用的。

要使用WebView不造成內(nèi)存泄漏,首先應(yīng)該做的就是不能在xml中定義webview節(jié)點(diǎn),而是在需要的時(shí)候動(dòng)態(tài)生成。即:可以在使用WebView的地方放置一個(gè)LinearLayout類似ViewGroup的節(jié)點(diǎn),然后在要使用WebView的時(shí)候,動(dòng)態(tài)生成即:

WebView mWebView = new WebView(getApplicationgContext()); LinearLayout mll= findViewById(R.id.xxx); mll.addView(mWebView);

, 然后一定要在onDestroy()方法中顯式的調(diào)用

protected void onDestroy() { super.onDestroy(); mWebView.removeAllViews(); mWebView.destroy()}

;注意:new WebView(getApplicationgContext());必須傳入ApplicationContext如果傳入Activity的Context的話,對(duì)內(nèi)存的引用會(huì)一直被保持著。有人用這個(gè)方法解決了當(dāng)Activity被消除后依然保持引用的問題。但是你會(huì)發(fā)現(xiàn),如果你需要在WebView中打開鏈接或者你打開的頁面帶有flash,獲得你的WebView想彈出一個(gè)dialog,都會(huì)導(dǎo)致從ApplicationContext到ActivityContext的強(qiáng)制類型轉(zhuǎn)換錯(cuò)誤,從而導(dǎo)致你應(yīng)用崩潰。這是因?yàn)樵诩虞dflash的時(shí)候,系統(tǒng)會(huì)首先把你的WebView作為父控件,然后在該控件上繪制flash,他想找一個(gè)Activity的Context來繪制他,但是你傳入的是ApplicationContext。后果,你可以曉得了哈。

于是大牛們就Activity銷毀后還保持引用這個(gè)問題,提供了另一種解決辦法:既然你不能給我刪除引用,那么我就自己來吧。于是下面的這種方法誕生了:

(作者說這個(gè)方法是依賴android.webkit implementation有可能在最近的版本中失敗)

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) { }}

然后在Activity中調(diào)用上面的方法:

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setConfigCallback((WindowManager)getApplicationContext().getSystemService(Context.WINDOW_SERVICE));}public void onDestroy() { setConfigCallback(null); super.onDestroy();}

該反射方法在我的實(shí)驗(yàn)中(2.3.6)確實(shí)有些用處,在應(yīng)用內(nèi)存占用到70M左右的時(shí)候會(huì)明顯釋放到50M或者60M然后的釋放就有些緩慢,其實(shí)就是看不出來了。之前在沒使用該方法的時(shí)候可能達(dá)到120M。

但是!!!我們的應(yīng)用要求占用內(nèi)存更低啊,這腫么拌?涼拌么?No。在各種糾結(jié)之后,終于找到了終極解決辦法!!!該辦法適用于我們的需求,在退出WebView的界面之后,迅速回收內(nèi)存。要問這個(gè)方法是什么,不要9999,不要8999,只要你仔細(xì)看好下面一句話:那就是為加載WebView的界面開啟新進(jìn)程,在該頁面退出之后關(guān)閉這個(gè)進(jìn)程。

這一點(diǎn)說了之后,你懂了吧?

但是在這個(gè)其中,殺死自己進(jìn)程的時(shí)候又遇到了問題,網(wǎng)上介紹的各種方法都不好使,

killBackgroundProcesses(getPackageName());各種不好用,最后使用System.exit(0);直接退出虛擬機(jī)(Android為每一個(gè)進(jìn)程創(chuàng)建一個(gè)虛擬機(jī)的)。這個(gè)肯定不用糾結(jié)了,一旦退出,內(nèi)存里面釋放。聽濤哥說QQ也是這么做。

最后英雄要問出處,附上大牛解說引起該問題的出處

這個(gè)泄漏出現(xiàn)在external/webkit/Source/WebKit/android/WebCoreSupport/UrlInterceptResponse.cpp.中。具體我自己真心沒有深入研究。大家有興趣的話,可以看看哈。

--- a/Source/WebKit/android/WebCoreSupport/UrlInterceptResponse.cpp+++ b/Source/WebKit/android/WebCoreSupport/UrlInterceptResponse.cpp@@ -63,10 +63,10 @@ public: JNIEnv* env = JSC::Bindings::getJNIEnv(); // Initialize our read buffer to the capacity of out. if (!m_buffer) {- m_buffer = env->NewByteArray(out->capacity());- m_buffer = (jbyteArray) env->NewGlobalRef(m_buffer);+ ScopedLocalRef<jbyteArray> buffer_local(env, env->NewByteArray(out->capacity()));+ m_buffer = static_cast<jbyteArray>(env->NewGlobalRef(buffer_local.get())); } int size = (int) env->CallIntMethod(m_inputStream, m_read, m_buffer); if (checkException(env) || size < 0) return; // Copy from m_buffer to out.

還有一個(gè)問題要說的,也是在WebView使用的時(shí)候出現(xiàn)的問題:WebView中包含一個(gè)ZoomButtonsController,當(dāng)使用web.getSettings().setBuiltInZoomControls(true);啟用該設(shè)置后,用戶一旦觸摸屏幕,就會(huì)出現(xiàn)縮放控制圖標(biāo)。這個(gè)圖標(biāo)過上幾秒會(huì)自動(dòng)消失,但在3.0系統(tǒng)以上上,如果圖標(biāo)自動(dòng)消失前退出當(dāng)前Activity的話,就會(huì)發(fā)生ZoomButton找不到依附的Window而造成程序崩潰,解決辦法很簡單就是在Activity的ondestory方法中調(diào)用web.setVisibility(View.GONE);方法,手動(dòng)將其隱藏,就不會(huì)崩潰了。在3.0一下系統(tǒng)上不會(huì)出現(xiàn)該崩潰問題,真是各種崩潰,防不勝防啊!

最后還有內(nèi)存泄漏的一些個(gè)建議:

In summary, to avoid context-related memory leaks, remember the following:

Do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself)Try using the context-application instead of a context-activityAvoid non-static inner classes in an activity if you don’t control their life cycle, use a static inner class and make a weak reference to the activity inside

And remember that a garbage collector is not an insurance against memory leaks. Last but not least, we try to make such leaks harder to make happen whenever we can.

來自:http://my.oschina.net/zhibuji/blog/100580

標(biāo)簽: Android
相關(guān)文章:
主站蜘蛛池模板: 国产成人综合洲欧美在线 | 亚洲经典乱码在线播 | 日韩一区二区三区在线免费观看 | 亚洲国产高清在线 | 欧美一级免费大片 | 国产啪精品视频网免费 | 日韩欧美三级在线观看 | 欧美日韩中文字幕在线观看 | 亚洲精品无码专区在线播放 | 亚洲 欧美 精品 中文第三 | 一本一道波多野结衣456 | 看一级特黄a大片国产 | 日韩欧美精品综合一区二区三区 | 日韩一级黄色毛片 | 另类专区国产在线视频 | 精品国产杨幂在线观看福利 | 18视频免费网站 | a一级毛片录像带 录像片 | 亚洲欧美日韩在线一区二区三区 | 99久久伊人一区二区yy5o99 | 青青草国产免费国产是公开 | 99精品免费在线观看 | 日韩伦理一区二区三区 | 俄罗斯黄色一级片 | 99久在线观看| 男人天堂国产 | 国内自拍视频在线看免费观看 | 国产精品一区亚洲一区天堂 | 久草在线视频网 | 国产九九精品视频 | www.99视频| 免费看一区二区三区 | 杨幂精品国产专区91在线 | 精品国产免费观看久久久 | 成人免费观看永久24小时 | 免费黄网大全 | 一级毛片真人不卡免费播 | 欧美成人午夜片一一在线观看 | 99精品观看 | 国产精品亚洲片在线观看不卡 | 欧美精品成人3d在线 |