Skip to content
阅读进度

Handler 导致的内存泄漏是如何发生的?如何使用 WeakReference 避免? ​

返回 性能与稳定性 目录

标准回答 ​

典型引用链是 MessageQueue → Message/Runnable → Handler 或闭包 → Activity。可以用静态 Handler 配合 WeakReference 读取页面,但更关键的是在适当生命周期移除未执行消息、取消任务,且 Runnable 本身也不能再次强引用页面。

通俗例子 ​

发出一分钟后执行的消息,十秒后关闭页面;剩下五十秒内,任务可能仍引用页面。清理无用消息,弱引用取出后还要判空和检查状态。

深入解释 ​

**为什么延迟消息会留住页面:**尚未执行的 Message 或 Runnable 留在 MessageQueue 中,回调对象可能再指向 Handler 或 Activity,所以页面关闭后仍有一条可达路径。

**弱引用有什么边界:**WeakReference 不阻止回收,但回调执行时对象可能已经消失,也可能虽然存在却不再适合更新。仍要判空、核对生命周期,并移除不需要的任务。

示例代码 ​

java
private final Handler main = new Handler(Looper.getMainLooper());
private final Runnable refresh = this::refreshUi;
@Override protected void onDestroy() {
    main.removeCallbacks(refresh);
    super.onDestroy();
}

易混淆点 ​

WeakReference 不会取消任务,也不会自动避免所有其他强引用。

内容来源 ​

用完整回答理解机制,用真实证据解释项目。