android.os.Message和/或Handler.removeCallback中的内存泄漏?

时间:2012-10-23 23:43:14

标签: android

我的活动如下所示:

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上下文的内存泄漏。

android.app.Activity的merge_shortest_paths的结果,不包括使用Eclipse Memory Analyzer工具的幻像,软,弱等引用: enter image description here

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

不应该调用removeCallbacks从队列中删除对runnable对象的任何引用吗?为什么我泄漏了背景?

1 个答案:

答案 0 :(得分:2)

要尝试的东西:

根据android文档:

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

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

您应该在onPause取消注册您的runnable: 此回调主要用于保存活动正在编辑的任何持久状态,向用户显示“就地编辑”模型,并确保在没有先杀死此活动的情况下没有足够的资源来启动新活动时不会丢失任何内容。这也是一个很好的做法,例如停止动画和其他消耗大量CPU的事情,以便尽快切换到下一个活动,或者关闭独占访问的资源,如摄像头。

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

在刷新时看不到你在做什么,很难说,由于活动参考是刷新方法中引用的活动范围,它可能会泄漏。