內存泄露是咱新手比較頭痛的問題,由於它不像崩潰,在開發環境能夠根據提示的錯誤信息排查問題。java
你都不知道咱的app是否哪一個犄角旮旯藏着一個吞噬內存的黑洞。android
排查android 內存泄露比較底層高端的作法:使用官方的內存分析工具(MAT), 比較好的兩篇入門文章:(一) 和 (二)git
然而這個過程比較考驗耐心,github
咱新手也能夠選擇另一款App的插件leakcanary,集成了這個插件,咱們在使用app的時候,遇到內存泄露點,它就會彈出通知,並告知泄漏點(release下不會彈框)。web
我們就用本身作的博客園app客戶端來測試內存泄露的問題。app
dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' }
@Override public void onCreate() { super.onCreate(); LeakCanary.install(this); }
接下來就是使用App,遇到內存泄漏,leakCanary會自動在手機裏建立一個app來描述泄漏信息ide
咱們的程序被測出了一個泄漏點,打開桌面以下圖標工具
leakCanary對內存泄露的描述、引用鏈很是詳細;這樣人性化的提示信息,能很是快的定位問題所在測試
觀察提示信息,咱們發現出現這個問題的緣由仍是由於匿名類隱式引用Activity,致使Activity回收不掉。出現問題的地方:gradle
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); } }