题目
Android中避免内存泄漏的常见方法
信息
- 类型:问答
- 难度:⭐
考点
内存泄漏原理,Context引用管理,匿名内部类使用
快速回答
避免Android内存泄漏的核心方法:
- 避免静态变量持有Context:使用Application Context代替Activity Context
- 及时解注册监听器:在onDestroy()中解除广播、回调等绑定
- 谨慎使用非静态内部类:改用静态内部类+WeakReference
- 关闭耗时资源:及时释放Cursor、FileStream等资源
1. 原理说明
内存泄漏指对象不再被使用时仍被GC Root引用,导致无法被垃圾回收。在Android中常见于:
- 生命周期错配:长生命周期对象持有短生命周期对象(如Activity)
- 未释放资源:广播、监听器、IO流等未及时关闭
- 内部类隐式引用:非静态内部类默认持有外部类引用
2. 常见场景与解决方案
场景1:静态变量持有Activity引用
错误代码示例:
public class MyUtils {
private static Context sContext; // 危险!
public static void init(Context context) {
sContext = context; // 若传入Activity会导致泄漏
}
}修复方案:
- 使用Application Context:
sContext = context.getApplicationContext() - WeakReference包装:
private static WeakReference<Context> sContextRef;
场景2:未解注册监听器
错误代码示例:
public class MainActivity extends Activity {
private SensorManager sensorManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
sensorManager.registerListener(sensorListener); // 注册监听
}
// 缺少onDestroy解注册
}修复方案:
@Override
protected void onDestroy() {
super.onDestroy();
sensorManager.unregisterListener(sensorListener); // 必须解注册
}场景3:Handler导致泄漏
危险代码:
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 隐式持有Activity引用
}
};安全方案:
// 1. 静态内部类 + WeakReference
private static class SafeHandler extends Handler {
private final WeakReference<MainActivity> mActivity;
SafeHandler(MainActivity activity) {
mActivity = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
MainActivity activity = mActivity.get();
if (activity != null) {
// 安全操作
}
}
}
// 2. 在onDestroy清除消息
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}3. 最佳实践
- 使用
LeakCanary库自动检测内存泄漏 - 遵循谁注册谁解注册原则
- 对Bitmap等大对象使用
recycle() - 避免在循环中创建临时对象
4. 常见错误
- 在Fragment中直接使用
getActivity()而不检查null - 在AsyncTask中直接操作UI组件
- 使用匿名内部类作为回调(改用静态内部类)
5. 扩展知识
- GC Root类型:静态变量、线程栈变量、JNI引用等
- 内存分析工具:Android Profiler, MAT工具
- 常见泄漏场景:单例模式、动画未取消、WebView等