zoukankan      html  css  js  c++  java
  • 【android内存泄露】 WebView篇

    在咱的博客园app里,新闻的内容使用WebView展示的。在测试中,咱重复进入、退出某个新闻10多次,观察到

    Objects一直在不断增长,反复触发GC,但是一直回收不了,占用的内存越来越高,于是警觉到这个WebView可能泄露内存了

    如下:

    在StackOverFlow上搜了下android webview memory leak(国内搜索结果质量太差,新手朋友推荐去这个网站搜答案)

    里面有个回答大概的意思是:

    我们在xml里面定义的WebView标签,默认这个Activity就被这个webView作为Context参数所持有了,因此,当这个Activity结束了想释掉放自己时,但是任然被webView所引用,因此GC回收不了,造成内存泄露

    解决之道就是

    1: 使用容器包裹WebView

    <FrameLayout
        android:id="@+id/web_container"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>

    2:手动创建WebView,使用ApplicationContext作为参数。在Ondestroy,调用容器的removeAllViews,同时调用webView的 destroy

    public class TestActivity extends Activity {
        private FrameLayout mWebContainer;
        private WebView mWebView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.your_layout);
    
            mWebContainer = (FrameLayout) findViewById(R.id.web_container);
            mWebView = new WebView(this);
            mWebContainer.addView(mWebView);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            mWebContainer.removeAllViews();
            mWebView.destroy();
        }
    }

    修改之后,反复测试,发现gc都能正常回收webView的资源了,非常好

    最后给上android如何回避内存泄露的一些建议,原文如下

    • 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-activity instead of a  context-application
    • Avoid 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. The solution to this issue is to use a static inner class with a WeakReference to the outer class, as done in ViewRoot and its W inner class for instance

    大体的意思就是,内存不能被回收,很多情况下,都是因为Activity被某个元素持有引用导致GC无法回收的。

    因此

    1:保持activity持有对象的生命周期和activity是一致的。(特别是各种异步操作生命周期会比activity长)

    2:使用Activity来代替全局对象Application,只有在你知道为啥使用Application长生命周期的时候,才去用它。 http://stackoverflow.com/questions/7298731/when-to-call-activity-context-or-application-context

    3:注意Activity的内部类会持有Activity的隐式引用(不然你咋能访问外部类的变量。。),因此使用static修饰内部类消除外部类隐式引用,并用weakReference访问外部类的属性。一个例子

  • 相关阅读:
    94. Binary Tree Inorder Traversal
    101. Symmetric Tree
    38. Count and Say
    28. Implement strStr()
    实训团队心得(1)
    探索性测试入门
    LC.278. First Bad Version
    Search in Unknown Sized Sorted Array
    LC.88. Merge Sorted Array
    LC.283.Move Zeroes
  • 原文地址:https://www.cnblogs.com/kimmy/p/4791657.html
Copyright © 2011-2022 走看看