編輯:關於Android編程
(該文章,引自零號路的私人博客,本人在浏覽框架的開發過程中,用該方式,規避了內存洩露的問題。)
在Android5.1系統中,會發現App存在 WebView 洩漏情況,還比較嚴重。並且只是發生在 Android 5.1 系統。
GC roots 如下:
每新打開一次這個WebViewActivity,就會發生就會發生一次改Webview實例無法釋放,新增一個對象。
上圖中的兩個 AppSearchWebView實例,就是由於打開了兩次導致。
出現了這個問題分析起來還是比較簡單的,根據這個引用關系,我們可以直觀的看到是由於 Appsearch(extends Application)的 mComponentCallbacks 一直在強引用AWComponentCallbacks,導致無法釋放。然後AWComponentCallbacks -> AWContents > AppSearchWebView。
通過分析代碼發現關鍵在於 AwContents 這裡的 AwComponentsCallbacks 為什麼沒有釋放。
@Override
public void onAttachedToWindow() {
if (isDestroyed()) return;
if (mIsAttachedToWindow) {
Log.w(TAG, "onAttachedToWindow called when already attached. Ignoring");
return;
}
......
mComponentCallbacks = new AwComponentCallbacks();
mContext.registerComponentCallbacks(mComponentCallbacks);
}
@Override
public void onDetachedFromWindow() {
if (isDestroyed()) return;
if (!mIsAttachedToWindow) {
Log.w(TAG, "onDetachedFromWindow called when already detached. Ignoring");
return;
}
......
if (mComponentCallbacks != null) {
mContext.unregisterComponentCallbacks(mComponentCallbacks);
mComponentCallbacks = null;
}
......
}
看這段代碼看不出來什麼問題,onAttach的時候 register,detach的時候 unregister, 不會存在問題。
但是為什麼呢?
難道是由於 if (isDestroyed()) return 這條return引起的?
當調用 Webview.destroy() 後 這個判斷 返回true。
我們看下哪裡調用了 webview.destroy()
// source from WebViewActivity
@Override
protected void onDestroy() {
super.onDestroy();
if (mWebView != null) {
mWebView.destroy();
}
}
很多應用應該都是這麼做的,包括系統浏覽器,在Activity destroy的時候,調用 webview的destroy。並且一直工作的很好。
通過調試發現,確實是由於此調用導致的。onDestroy 發生在 onDetach 之前。
那為什麼 android 5.1 之前的代碼沒有問題呢?
看下代碼:
// AwContents.java
@Override
public void onDetachedFromWindow() {
if (!mIsAttachedToWindow) {
Log.w(TAG, "onDetachedFromWindow called when already detached. Ignoring");
return;
}
......
if (mComponentCallbacks != null) {
mContext.unregisterComponentCallbacks(mComponentCallbacks);
mComponentCallbacks = null;
}
......
}
相對於 5.1 的代碼少了那句if (isDestroyed()) return;
解決方案可以:在destroy之前,把webview 從 parent 中 remove 掉,同樣可以提前detach。
protected void onDestroy() {
if (mWebView != null) {
((ViewGroup) mWebView.getParent()).removeView(mWebView);
mWebView.destroy();
mWebView = null;
}
super.onDestroy();
}
WebView組件本身就是一個浏覽器實現,Android5.0增強的WebView基於Chromium M37,直接支持WebRTC、WebAudio、WebGL。開發者
前言:因為要做一個設置開機畫面的功能,主要是讓用戶可以設置自己的開機畫面,應用層需要做讓用戶選擇開機畫面圖片的功能。所以需要做一個簡單的圖片浏覽選擇程序。最後選用Gall
前面幾篇我們講解了 QtAndroid 名字空間的基本用法,這次我們使用前面講過的方法和類庫,展示一些簡單的小示例。我在《Qt on Android核心編程》一書中主要通
絕大多數項目總都會有各種形形色色的列表界面,但其實這些界面的區別就在於列表子項的布局不同和點擊事件的響應不同而已,然而每次有個新的列表界面從適配器到Activity都需要