1.单例模式造成的内存泄漏
public class Utils {
private static Utils sInstance;
private Context mContext;
private AppSettings(Context context) {
this.mContext = context;
}
public static Utils getInstance(Context context) {
if (sInstance == null) {
sInstance = new Utils(context);
}
return sInstance;
}
}
以上单例 context 参数如果传入的是 Activity,Service的上下文对象就会造成内存泄漏,因为静态单例sInstance对象生命周期与 Application 一样长,当 Activity或 Service 销毁时 Utils 还在引用 Activity 或 Service,导致 Activity,Service 不能被回收。
2.非静态内部类内存泄漏
非静态内部类默认持有外部类对象引用。生命周期与应用一样长,所以导致外部类销毁的时候内部类仍然引用外部类,导致外部类不能被回收。
解决方法:改成静态内部类.
典型场景:
//线程匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
// 模拟相应耗时逻辑
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
// 模拟相应耗时逻辑
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}.execute();
//线程写成静态内部类
private static class MyThread implements Runnable {
public void run() {
SystemClock.sleep(20000);
}
}
//Handler造成的内存泄漏
public class DemoActivity extends Activity {
private final Handler mLeakyHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// ...
}
}
}
由于消息队列持有 handler 引用,handler 又持有 activity 的引用,当消息队列中的消息还没有处理完,activity 就销毁,导致 activity引用仍被使用不能被回收。解决方法:使用静态内部类+弱引用(静态类不会引用 activity,通过弱引用来引用 activity 中的资源)
public static class MyHandler extends Handler {
//声明一个弱引用对象
WeakReference<MainActivity> mReference;
MyHandler(MainActivity activity) {
//在构造器中传入Activity,创建弱引用对象
mReference = new WeakReference<MainActivity>(activity);
}
public void handleMessage(Message msg) {
//在使用activity之前先判空处理
if (mReference != null && mReference.get() != null) {
mReference.get().text.setText("hello word");
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
3.静态变量导致内存泄露
静态变量的生命周期与应用一致,当变量被初始化后,它持有的引用到进程结束才会释放。要尽量少的使用静态变量,在适当时候设置 null。
4.未取消注册或回调导致内存泄露
如广播,EventBus注册,在 Activity 销毁后没有取消注册,activity 引用就会被一直持有。销毁时要取消注册。
5.资源对象未及时释放
如Cursor、Stream、Socket,Bitmap等在使用后要及时关闭。
6.集合中的对象未清理造成内存泄露
我们有时会用集合存储对象引用,当对象不用时没有清理集合导致集合越来越大,如果集合是静态的更会造成内存泄漏。要在适当时候clear集合,然后设置为 null。