6

我有一个如下所示的活动:

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 Tool 的 phantom、soft、weak 等引用: 在此处输入图像描述

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

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

4

1 回答 1

2

可以尝试的东西:

根据 android 文档:

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

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

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

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

如果没有看到您在刷新中所做的事情,很难说它可能由于活动引用而泄漏,这些活动引用是在刷新方法中引用的活动范围。

于 2013-07-27T02:01:50.957 回答