【问题标题】:Memory leak in android.os.Message and/or Handler.removeCallback?android.os.Message 和/或 Handler.removeCallback 中的内存泄漏?
【发布时间】:2012-10-23 23:43:14
【问题描述】:

我的活动如下所示:

class MyActivity extends Activity {
    Runnable refreshTimer = new Runnable() {
        public void run() {
            refresh();
        }
    };

    protected onCreate(...) {
        handler.postAtTime(refreshTimer, ...);
    }

    protected onDestroy() {
        handler.removeCallbacks(refreshTimer);
    }

    protected void refresh() { ... }
}

调用 onDestroy 后,由于某种原因,活动的 MessageQueue 中仍有消息包含对 MyActivity$0(刷新 Runnable)的引用。因为 MyActivity$0 隐式引用了 MyActivity,这会导致 MyActivity 上下文的内存泄漏。

使用 Eclipse Memory Analyzer Tool 对 android.app.Activity 的 merge_shortest_paths 的结果,不包括 phantom、soft、weak 等引用:

(上面的源代码是MAT转储中显示的实际对象关系的简化)

不应该调用 removeCallbacks 从队列中删除对可运行对象的任何引用吗?为什么我会泄露上下文?

【问题讨论】:

    标签: android


    【解决方案1】:

    尝试一下:

    根据 android 文档:

    OnDestroy: 在您的活动被销毁之前您收到的最后一个电话。这可能是因为 Activity 正在完成(有人在其上调用了 finish(),或者因为系统正在临时销毁该 Activity 实例以节省空间。您可以使用 isFinishing() 方法区分这两种情况。

    当您退出活动时,看起来仍有一堆排队的消息,并且取消注册的上下文没有调用取消回调。

    你应该做的是在onPause中注销你的runnable: 此回调主要用于保存活动正在编辑的任何持久状态,向用户呈现“就地编辑”模型,并确保如果没有足够的资源来启动新活动而没有首先杀死该活动,则不会丢失任何内容。这也是一个很好的地方来做一些事情,比如停止动画和其他消耗大量 CPU 的事情,以便尽快切换到下一个活动,或者关闭诸如相机之类的独占访问资源。

    通常,Receiver 或“Scheduled”Runnable 将在 onResume 中注册,并在 onPause 中取消注册以实现更好的生命周期配对

    如果看不到您在刷新中所做的事情,很难判断,它可能由于在刷新方法中引用的活动范围内的活动引用而泄漏。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-27
      • 1970-01-01
      • 2010-12-02
      • 2013-11-08
      • 2016-05-03
      • 2011-11-25
      相关资源
      最近更新 更多