zoukankan      html  css  js  c++  java
  • 【android】通过leakCanary找出程序内存泄露点

    背景

    内存泄露是咱新手比较头痛的问题,因为它不像崩溃,在开发环境可以根据提示的错误信息排查问题。

    你都不知道咱的app是否哪个犄角旮旯藏着一个吞噬内存的黑洞。

    排查android 内存泄露比较底层高端的做法:使用官方的内存分析工具(MAT), 比较好的两篇入门文章:(一) 和 (二)

    然而这个过程比较考验耐心,

    咱新手也可以选择另外一款App的插件leakcanary,集成了这个插件,我们在使用app的时候,遇到内存泄露点,它就会弹出通知,并告知泄漏点(release下不会弹框)。

    实战

    咱们就用自己做的博客园app客户端来测试内存泄露的问题。

    1:集成leakCanary

    1.1:build.gradle里面:

     dependencies {
       debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'
       releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1'
     }

    1.2:Application父类的onCreate方法中添加:

     @Override
        public void onCreate() {
            super.onCreate();
            LeakCanary.install(this);
    }

     1.3:准备工作已经完毕

    接下来就是使用App,遇到内存泄漏,leakCanary会自动在手机里创建一个app来描述泄漏信息

    2:测试内存泄露

    我们的程序被测出了一个泄漏点,打开桌面如下图标

    leakCanary对内存泄露的描述、引用链非常详细;这样人性化的提示信息,能非常快的定位问题所在

    观察提示信息,我们发现出现这个问题的原因还是因为匿名类隐式引用Activity,导致Activity回收不掉。出现问题的地方:

    mWebView.setOnScrollListener(new ScrollWebView.OnScrollListener() {
                @Override
                public void onScroll(int x, int y) {
                    switchActionBar(y - mPreviousYPos);
                    mPreviousYPos = y;
                }
            });

    这个泄漏点的解决之道有很多,在回收的时候,只要确保该Activity没被其他对象持有强引用就好了。

    咱的解决之道是使用弱引用,这样调用者就不用关心强引用可能导致的内存泄露的问题了。

    package zhexian.learn.cnblogs.ui;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.webkit.WebView;
    
    import java.lang.ref.WeakReference;
    
    /**
     * 可以滚动的webView
     */
    public class ScrollWebView extends WebView {
        private WeakReference<OnScrollListener> mOnScrollListener;
    
        public ScrollWebView(final Context context) {
            super(context);
        }
    
        public ScrollWebView(final Context context, final AttributeSet attrs) {
            super(context, attrs);
        }
    
        public ScrollWebView(final Context context, final AttributeSet attrs, final int defStyle) {
            super(context, attrs, defStyle);
        }
    
        @Override
        protected void onScrollChanged(final int l, final int t, final int oldl, final int oldt) {
            super.onScrollChanged(l, t, oldl, oldt);
            OnScrollListener listener = mOnScrollListener.get();
    
            if (listener != null)
                listener.onScroll(l, t);
        }
    
        public void setOnScrollListener(final OnScrollListener onScrollListener) {
            mOnScrollListener =new WeakReference<>(onScrollListener) ;
        }
    
        public interface OnScrollListener {
            void onScroll(int x, int y);
        }
    }
  • 相关阅读:
    推荐一个采用方便程序员在线动画学习常用算法的良心网站
    你的ABAP程序给佛祖开过光么?来试试Jerry这个小技巧
    我在德国做SAP CRM One Order redesign工作的心得
    我做SAP CRM One Order redesign的一些心得体会
    一个最简单的WebSocket hello world demo
    推荐一个好用的以多tab标签方式打开windows CMD的工具
    SAP CX Upscale Commerce : SAP全新推出的电商云平台
    TCP socket和web socket的区别
    SAP 前端技术的演化史简介
    Fiori Fundamentals和SAP UI5 Web Components
  • 原文地址:https://www.cnblogs.com/kimmy/p/4826432.html
Copyright © 2011-2022 走看看