-
打开 MemoryAnalyzer.exe 点击左上角 File 菜单中的 Open Heap Dupm
- 查看内存泄漏中的 GC Roots 强引用
这里我们得知是一个 ilsLoginListener 引用了 LoginView,我们来看下代码最后怎么解决的。
代码中我们找到了 LoginView 这个类,发现是一个单例中的回调引起的内存泄漏,下面怎么解决勒,请看第七小点。
-
2种解决单例中的内存泄漏
-
将引用置为 null
/**
- 销毁监听
*/
public void unRemoveRegisterListener(){
mMessageController.unBindListener();
}
public void unBindListener(){
if (listener != null){
listener = null;
}
}
- 使用弱引用
//将监听器放入弱引用中
WeakReference listenerWeakReference = new WeakReference<>(listener);
//从弱引用中取出回调
listenerWeakReference.get();
- 通过第七小点就能完美的解决单例中回调引起的内存泄漏。
Android 中常见的内存泄漏经典案例及解决方法
- 单例
示例 :
public class AppManager {
private static AppManager sInstance;
private CallBack mCallBack;
private Context mContext;
private AppManager(Context context) {
this.mContext = context;
}
public static AppManager getInstance(Context context) {
if (sInstance == null) {
sInstance = new AppManager(context);
}
return sInstance;
}
public void addCallBack(CallBack call){
mCallBack = call;
}
}
- 通过上面的单列,如果 context 传入的是 Activity , Service 的 this,那么就会导致内存泄漏。
以 Activity 为例,当 Activity 调用 getInstance 传入 this ,那么 sInstance 就会持有 Activity 的引用,当 Activity 需要关闭的时候需要 回收的时候,发现 sInstance 还持有 没有用的 Activity 引用,导致 Activity 无法被 GC 回收,就会造成内存泄漏
- addCallBack(CallBack call) 这样写看起来是没有毛病的。但是当这样调用在看一下勒。
//在 Activity 中实现单例的回调
AppManager.getInstance(getAppcationContext()).addCallBack(new CallBack(){
@Override
public void onStart(){
}
});
这里的 new CallBack() 匿名内部类 默认持有外部的引用,造成 CallBack 释放不了,那么怎么解决了,请看下面解决方法
解决方法:
-
getInstance(Context context) context 都传入 Appcation 级别的 Context,或者实在是需要传入 Activity 的引用就用 WeakReference 这种形式。
-
匿名内部类建议大家单独写一个文件或者
public void addCallBack(CallBack call){
WeakReference mCallBack= new WeakReference(call);
}
- Handler</