美文网首页
LeakCanary 内存泄露检测实践与解决方法总结

LeakCanary 内存泄露检测实践与解决方法总结

作者: ahking17 | 来源:发表于2016-08-15 17:31 被阅读1103次
    建立LeakCanaery的检测环境
    1. 修改chrome的build.gradle
    apply plugin: 'com.android.application'
    
    dependencies {
        compile fileTree(dir: 'libs', exclude: 'android-support-multidex.jar', include: '*.jar')
        compile 'com.android.support:multidex:1.0.0'
        compile project(':mediaplayer')
        compile project(':web_contents_delegate_android')
        compile project(':browser_I')
        compile project(':chromium_gen')
        compile files('libs/hugo-annotations-1.2.1-sources.jar')
        compile files('libs/decrawso.jar')
        compile files('libs/qihoospeechrecognition.jar')
        compile files('libs/QHStatAgent.jar')
        compile files('libs/adsdk_0.1.16.1125.jar')
        compile files('libs/andfix.jar')
        compile files('libs/opensdk-release.jar')
    //添加下面2行
        debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'
        releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3'
    }
    
    2. 修改ChromeApplication.java
        @Override
        public void onCreate() {
            UmaUtils.recordMainEntryPointTime();
            super.onCreate();
            LeakCanary.install(this);
    
    3. 手动测试, 当发生memory leak的时候就会在桌面创建出Leaks图标

    经过测试, 确实发现浏览器有不少内存泄露的地方.

    memory_leak.png
    4. 解决这些问题的code patch
    memory_leak_code_patch.png
    常见的代码错误汇总
    场景1. 进入某个activity, 然后退出, 再进入.
    场景2. 频繁退出, 进入浏览器.
    1. static 对象持有了具体activity的context

    static的对象(生命周期是整个app运行期), 在创建时传入了某个具体的Activity对象, 当这个activity退出时(onDestroy()被调用), 这个activity对象无法被释放.
    解决办法: static对象如果要用到context的话, 就要使用applicationContext, 不要使用activity context.

    例如:

    public class ToastHelper implements BrowserOnDestroyListener {
        private static Toast mToast;
    
        public void init(Context context) {
            if (mToast == null) {
                try {
                    mToast = new Toast(context);
                    mToast.setDuration(Toast.LENGTH_SHORT);
                    mToast.setView(inflate.inflate(R.layout.transient_notification, null));
                } catch (Exception e) {
                }
            }
        }
    
    //应该改为:
        public void init(Context context) {
            if (mToast == null) {
                try {
                    mToast = new Toast(context.getApplicationContext());
                    mToast.setDuration(Toast.LENGTH_SHORT);
                    mToast.setView(inflate.inflate(R.layout.transient_notification, null));
                } catch (Exception e) {
                }
            }
        }
    
    2. 对单例的Manager, 只调用了addListener(), 忘记在销毁时调用removeListener().

    例如:

    public class BottomMenuBar extends LinearLayout {
        public BottomMenuBar(Context context, AttributeSet attrs) {
            super(context, attrs);
            mContext = context;
            setOrientation(HORIZONTAL);
            ThemeModeManager.getInstance().addThemeModeListener(this, true);
        }
    
    //需要添加下面的代码
    //否则ThemeModeManager的listeners会一直持有BottomMenuBar的对象, 导致BottomMenuBar被销毁后, 它所占的内存无法被回收.
        @Override
        protected void onDetachedFromWindow() {
            super.onDetachedFromWindow();
            ThemeModeManager.getInstance().removeThemeModeListener(this);
        }
    
    }
    
    

    refer to:
    http://www.liaohuqiu.net/cn/posts/leak-canary-read-me/

    ======DONE======

    相关文章

      网友评论

          本文标题:LeakCanary 内存泄露检测实践与解决方法总结

          本文链接:https://www.haomeiwen.com/subject/lxiusttx.html