【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);
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM