Android 内存泄漏相关
在了解内存泄漏之前,先来了解下Java 的引用类型
-
强引用:即默认的引用类型,例如
StringBuffer sb = new StringBuffer();就是sb 持有了StringBuffer的强引用类型。
-
弱引用:即WeakReference,其指向的对象只有在GC执行时才会被回收。
-
软引用:即SoftReference,其指向的对象只有在内存不足的时候进行回收。
-
虚引用:即phantomReference,与ReferenceQueue 结合,用作记录该引用指向的对象已被销毁。
在Android 中内存泄漏的场景很多,一般情况有:
- 长期持有了Activity(Context)。
- 忘记注销监听器或者观察者。
- 非静态内部类持有外部类的引用。
针对以上情况的一些解决方案:
- 尽量避免使用Activity 的Context,多使用Application 的Context,其生命周期为App的生命周期。
- 手动解除不必要的强引用关系。
- 使用弱引用或者软引用替换强引用关系。
- 将生命周期长的非静态内部类替换成静态内部类。
检测内存泄漏的方式主要有MAT,集成在了Android Studio 中,以及Square 开发的LeakCanary。
下面以Handler 的使用为例。
由于非静态内部类会持有外部类的引用,所以在Activity 中创建非静态的自定义Handler 可能会导致内存泄漏。
public class MainActivity extends Activity {
private final Handler mLeakyHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// ...
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLeakyHandler.postDelayed(new Runnable() {
@Override
public void run() {
// ...
}
}, 1000 * 60 * 10);
finish();
}
}
如果自定义的 Handler 中没有使用到外部类,就可以直接静态化避免不必要的引用外部类:
static final Handler mLeakyHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// ...
}
}
如果该自定义的 Handler 需要使用外部的 Activity 引用,可以使用弱引用来避免内存泄露:
private static class MyHandler extends Handler {
private final WeakReference<MainActivity> mActivityReference;
public MyHandler(MainActivity activity) {
mActivityReference = new WeakReference<MainActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
MainActivity activity = mActivityReference.get();
if (activity != null) {
// 使用弱引用一定要注意检查为空
}
}
}