上一节我们介绍了关于单例的内存泄露,这一节我们来看一下非静态内部类作为静态变量产生内存泄漏的情况
知识点
1.非静态内部类的实例持有外部类的强引用。
2.静态变量的生命周期和应用(Application)的生命周期一样长。
案例
我们来看一段代码
public class TestAct extends AppCompatActivity {
private static InnerClass mInnerClass = null;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_test);
if (mInnerClass == null) {
mInnerClass = new InnerClass();
}
}
class InnerClass {
}
}
在这个Activity中看似很好,每次创建activity的时候,静态实例并不会重新创建。那么我们来分析一下:
代码中有一个非静态内部类InnerClass,有一个静态变量mInnerClass,在代码中new InnerClass()创建了一个内部类的实例,这个实例就持有外部类(Activity)的强引用,这个实例赋值给静态变量之后,那么这个静态变量也就是静态实例,也会持有Activity的强引用,而该静态实例的生命周期和应用的生命周期一样长,这就导致了:由于这个静态实例持有activity的强引用,回收activity的时候而无法回收,也就是产生了内存泄漏。
解决方法
1.将该内部类设置为静态内部类(静态内部类不会持有外部类的引用),即如下代码:
public class TestAct extends AppCompatActivity {
private static InnerClass mInnerClass = null;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_test);
if (mInnerClass == null) {
mInnerClass = new InnerClass();
}
}
static class InnerClass {
}
}
2.将该内部类抽取出来封装成一个单例,如果需要使用Context,就使用Application的Context。
public class InnerClass {
private volatile static InnerClass instance;
private InnerClass(Context context) {
}
public static InnerClass getInstance(Context context) {
if (instance == null) {
synchronized (InnerClass.class) {
if (instance == null) {
instance = new InnerClass(context.getApplicationContext());
}
}
}
return instance;
}
}
public class TestAct extends AppCompatActivity {
private static InnerClass mInnerClass = null;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_test);
if (mInnerClass == null) {
mInnerClass = InnerClass.getInstance(this);
}
}
}
3.还有一种很简单粗暴的方法,就是在activity销毁的时候,将这个静态内部类设置为空。如下
public class TestAct extends AppCompatActivity {
private static InnerClass mInnerClass = null;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_test);
if (mInnerClass == null) {
mInnerClass = InnerClass.getInstance(this);
}
}
@Override
protected void onDestroy() {
mInnerClass = null;
super.onDestroy();
}
}
好了,非静态内部类作为静态变量的内存泄漏也已经讲得很清楚了。