题目
简述Android中Handler引起内存泄漏的原因及解决方案
信息
- 类型:问答
- 难度:⭐
考点
内存泄漏,Handler机制,弱引用
快速回答
Handler引起内存泄漏的主要原因及解决方案:
- 原因:Handler持有Activity的隐式引用导致无法回收
- 解决方案:
- 使用静态内部类+弱引用
- 在onDestroy()中移除回调
原理说明
当Handler作为Activity的内部类时,会隐式持有外部类Activity的引用。如果Handler中有未执行完的延迟消息(如postDelayed),会导致Activity无法被GC回收,即使Activity已被销毁。
代码示例
// 错误实现:非静态内部类导致泄漏
class LeakyActivity extends Activity {
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 更新UI
}
};
}
// 正确实现:静态内部类+弱引用
class SafeActivity extends Activity {
private static class SafeHandler extends Handler {
private final WeakReference<SafeActivity> mActivityRef;
SafeHandler(SafeActivity activity) {
mActivityRef = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
SafeActivity activity = mActivityRef.get();
if (activity != null) {
// 安全更新UI
}
}
}
private final Handler mHandler = new SafeHandler(this);
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null); // 移除所有消息
}
}最佳实践
- 始终使用静态内部类+WeakReference封装Handler
- 在Activity的
onDestroy()中调用handler.removeCallbacksAndMessages(null) - 避免在Handler中执行耗时操作
常见错误
- 在Activity中直接创建匿名Handler内部类
- 忘记移除延迟消息(尤其postDelayed)
- 在Handler中持有Context的强引用
扩展知识
- 弱引用(WeakReference):GC时会自动回收,避免内存泄漏
- Looper消息机制:MessageQueue持有Message,Message持有Handler
- Android Studio的Memory Profiler工具可检测内存泄漏
- 其他泄漏场景:静态变量、单例模式、未关闭的资源(Cursor/Stream)