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访问外部类的属性。一个例子

  • 相关阅读:
    C# 异步(上)
    依赖注入框架Ninject
    依赖注入实例
    职场闲言
    Excel 使用VBA或宏----简单笔记
    Excel单元格锁定及解锁
    current transaction is aborted, commands ignored until end of transaction block
    JAVA_HOME is not defined correctly
    Multiple encodings set for module chunk explatform "GBK" will be used by compiler
    springBoot 整合 RabbitMQ 的坑
  • 原文地址:https://www.cnblogs.com/kimmy/p/4791657.html
Copyright © 2011-2022 走看看