一、Handler引起的泄漏
假如程序如下方式书写:
Handler mHandler = new Handler() {
@Override
public void handleMessage(android.os.Message msg) {
super.handleMessage(msg);
};
};
由于mHandler作为内部类,间接持有了对Activity的引用。所以当Activity即将要销毁的时候,如果mHandler消息没有及时处理完,就会导致Activity不能被释放。这样就导致了内存泄漏。
RE:可以通过Android studio中的静态检测工具来检测项目中可能存在的Handler泄漏
解决方式:1.优先使用静态的内部类 2.Handler使用弱引用
由于界面使用Handler比较多,所以通过一个自定义Handler来简化使用流程。代码如下:
/**
*
* 更新UI的Handler基类 避免匿名自定义Handler,而导致的内存泄露 使用时定义静态内部类,该类简化了弱引用的使用流程
*
* @author ChenP
* @date 2016年8月29日 上午11:04:32
*/
public class BaseUIHandler<T> extends Handler {
/**
* UI界面对象的弱引用对象
*/
protected WeakReference<T> refInstance;
/**
* 构造函数
*
* @param target
* UI界面对象实例
*/
protected BaseUIHandler(T target) {
refInstance = new WeakReference<T>(target);
}
/**
* 获取UI对象实例(根据弱引用对象获取,不会导致内存泄露)
*
* @return
* @return T
* @author ChenP
* @date 2016年8月29日 上午11:05:22
*/
protected T get() {
return refInstance.get();
}
}
这样在界面中使用的时候,
static class UIHandler extends BaseUIHandler<CldAndActivity> {
protected UIHandler(CldAndActivity target) {
super(target);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
CldAndActivity instance = get();
if (instance == null) {
return;
}
switch (msg.what) {
case 0:
/**
* 处理hanlder事务。----由于静态内部类不能访问外部类的方法和变量,可以通过对instance的引用来处理。
* 比如写一个dealHandler()方法,通过instance.dealHandler()来处理。
*/
break;
}
}
}
二、静态的成员变量(如果Drawable)引起泄漏
private static Drawable sBackground;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this);
label.setText("Leaks are bad");
if (sBackground == null) {
sBackground = getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);
setContentView(label);
}
label.setBackgroundDrawable这个方法内部会调用 d.setCallback(this);持有对TextView的引用。但是在4.0之后才使用弱引用
public final void setCallback(Callback cb) {
mCallback = new WeakReference<Callback>(cb);
}
所以在4.0之前如果是静态的Drawable,持有对Activity的引用。就会导致内存泄漏
解决方式:在Activity将要onDestroy的时候,调用sBackgroundDrawable.setCallback(null)。
三、非静态内部类的静态实例容易造成内存泄漏
public class MainActivityextends Activity
{
static Demo sInstance = null;
@Override
public void onCreate(BundlesavedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (sInstance == null)
{
sInstance= new Demo();
}
}
class Demo
{
voiddoSomething()
{
System.out.print("dosth.");
}
}
}
RE:Demo作为非静态内部类,持有对Activity的应用。静态的成员变量持有对Activity的引用,就会导致Activity不能回收。
四、单例模式、外部API保存了类、上下文Context的引用
Test.getInstance().init(new TestProgressListener ());
private class TestProgressListener implements ProgressListener {
/**
* @see com.cld.nv.frame.ICldProgressListener#onStart()
*/
@Override
public void onStart() {
}
}
如果单例模式、其他API内部保存了对非静态内部类or上下文Context的引用。也会间接导致持有对Activity的引用。导致内存泄漏