内存泄露是咱新手比较头痛的问题,由于它不像崩溃,在开发环境能够根据提示的错误信息排查问题。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); } }