首页 > 代码库 > WebView存在的内存泄漏

WebView存在的内存泄漏

## 0. Notice - earlier version

* 要使用WebView不造成内存泄漏,首先应该做的就是不能在xml中定义webview节点,而是在需要的时候动态生成。即:可以在使用WebView的地方放置一个LinearLayout类似ViewGroup的节点,然后在要使用WebView的时候,动态生成即:

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


然后一定要在onDestroy()方法中显式的调用:

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

注意: new  WebView(getApplicationgContext()) ;必须传入ApplicationContext如果传入Activity的Context的话,对内存的引用会一直被保持着。有人用这个方法解决了当Activity被消除后依然保持引用的问题。但是你会发现,如果你需要在WebView中打开链接或者你打开的页面带有flash,获得你的WebView想弹出一个dialog,都会导致从ApplicationContext到ActivityContext的强制类型转换错误,从而导致你应用崩溃。


## 1. What leads to Memory leak

### 1.1 InnerClass 

```java
public class InnerClassActivity extends Activity{
    private static Leak mLeak;
    class Leak {
        int a = 3;
        private Context mLeakContext;
        Leak(Context context) {
            mLeakContext = context;
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test);
        mLeak = new Leak(this);
        Toast.makeText(this, "This is InnerClassActivity", Toast.LENGTH_SHORT).show();
    }
}
```

### 1.2 Singleton 

```java
public class Singleton {
    private static Singleton instance;
    private Context mContext1;
    private Singleton(Context context) {
        this.mContext1 = context;
    }
 
    public static Singleton getInstance(Context context) {
        if(instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton(context);
                }
            }
        }
        return instance;
    }
}
```

### 1.3 webview - earlier version

```java
public class WebViewCreateActivity extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        setContentView(R.layout.webview_create);
        LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        WebView webView = new WebView(this);
        webView.setLayoutParams(layoutParams);
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setDomStorageEnabled(true);
        webView.loadUrl("https://www.baidu.com/");
        ll.addView(webView);
        Toast.makeText(this, "Hello", Toast.LENGTH_SHORT).show();
    }
}
```



## 2. How to detect the Memory Leak

### 2.1 Android Studio 

* GC manually 
* dump Java Heap

技术分享

### 2.2 MemoryLeak in Our Project

| 品牌 | 固件 | 泄漏点 | 
| ---    | ----   | -------- |
| 三星 | 4.0.4 | LightAppManager
| 小米 | 5.0.1 | LightAppManager/ mAccessibilityManager
| 华为 | 6.0   | LightAppManager/ mAccessibilityManager

#### 2.2.1 LightAppManager泄漏

3次手动GC后,内存的增长:
技术分享

泄漏点1: LightAppManager 泄漏
技术分享

泄漏点2: WebView-wrapper getSystemService泄漏
技术分享


## 3. 官方态度
It‘s 2016 now and, as far as I can see it, the issue still hasn‘t been resolved. I tested it on Nexus 5 and Nexus 6 with the latest WebView updates (since the component is now separate from the OS itself). Could someone, please, take a look at this issue?!  `

来源: https://code.google.com/p/android/issues/detail?id=9375


WebView存在的内存泄漏