单例模式
public void SingleInstanceTest {
private static SingleInstanceTest mInstance;
private Context mContext;
private SingleInstanceTest(Context context){
this.mContext = context.getApplicationContext();
}
public static SingleInstanceTest newInstance(Context context){
if(mInstance == null){
mInstance = new SingleInstanceTest(context);
}
return mInstance;
}
}
用到Activity或Context的实体类
使用弱引用(WeakReference)改进
public class Test{
private WeakReference<Context> mWeakReference;
public Test(Context context){
this.mWeakReference = new WeakReference<>(context);
}
public Context getContext(){
if(mWeakReference.get() != null){
return mWeakReference.get();
}
return null;
}
}
外部调用时
Test test = new Test(MainActivity.this);
非静态内部类/匿名类(耗时线程)
静态内部类和非静态内部类的对比
class对比 | 静态内部类 | 非静态内部类 |
---|---|---|
与外部class引用关系 | 如果没有传入参数就没有引用 | 自动获得强引用 |
被调用时需要外部实例 | 不需要 | 需要 |
能否调用外部class中的变量 | 不能 | 能 |
生命周期 | 自主的生命周期 | 依赖于外部类,甚至比外部类更长 |
解决
- 非静态内部类改成静态内部类
- 匿名类继承后成为静态内部类(Handler),并且在Activity的onDestroy()中移除所有消息,例如:
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
# 静态集合
>例如
static List<Object> objectList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Object obj = new Object();
objectList.add(obj);
obj = null;
}
例子中,循环多次将new出来的对象放入静态集合中,因为静态变量的生命周期和应用程序一致,而且他们所引用的对象Object也不能释放,造成了内存泄漏。
>解决:在静态集合使用后,删除元素,再将静态集合置空。如:
objectList.clear();
objectList = null;
其他情况
1.需要手动关闭的对象没有关闭
- 网络、文件流忘记关闭
- 手动注册广播,退出时忘记unregisterReceiver()
- Service执行完成后忘记stopSelf()
- EventBus等观察者模式的框架忘记手动解除注册
2.static关键字修饰的成员变量
3.ListView 的 Item 泄漏
排查内存泄漏的工具
1.Android Lint(Android studio提供的代码扫描分析工具)
2.leakcanary
本篇文章参照:Android 关于内存泄露,你必须了解的东西
网友评论