1

我对破坏活动和对象有疑问。

当我从 AsyncTask 附加和分离活动时,我不会从 asynctask 更改 ArrayAdapter(请参阅代码)。所以,我得到的是多个活动被附加和分离(应该改变方向),只有一个任务正在运行和修改一个适配器,而这个适配器又是创建任务的第一个活动的那个。因此,当我在 onCreate() 中附加任务时,我只是将适配器设置为包含任务的适配器,而该适配器又处理了所有值(在示例中只是一个虚拟数字列表)。

这怎么可能?我认为 onDestroy() 会擦除活动本身及其属性,因此在尝试从 AsynkTask 访问原始活动的 ArrayAdapter 时,我会得到一个空指针异常或类似的东西,但下面的代码有效!

private static class TestingTask extends AsyncTask<Void, Integer, Void> {

    private TestingActivity mActivity; // extends ListActivity
    private ArrayAdapter<String> mAdapter;
    private boolean mIsFinished;

    private TestingTask(Context activity) {
        attach(activity);
        mAdapter = (ArrayAdapter<String>)mActivity.getListAdapter();
        mIsFinished = false;
    }

    private void attach(Context activity) {
        mActivity = (TestingActivity)activity;
    }

    private void detach() {
        mActivity = null;
    }

    protected Void doInBackground(Void... params) {
        for (int i = 0; i < 100000; i++) {
            publishProgress(i);
        }
        return null;
    }

    protected void onProgressUpdate(Integer... values) {
        if (!isCancelled()) {
            mAdapter.add(values[0].toString());
        }
    }

    // ...
}

这是因为任务保持对 ArrayAdapter 对象的活动引用,因此它没有被删除?或者是别的什么?

我还经历了另一个“类似情况”,其中我从 onRetainNonConfigurationInstance() 返回了一个 Activity 的属性,比如说 A a,它对 B b 具有可见性(这是 Activity 的另一个属性)。然后,当尝试通过a访问b实例时,没有问题,我认为我需要一个包装器来保存两个实例(a和b),否则我会在尝试访问b时遇到异常(我这样做了实际上没有保存)。我不知道它是否与之前的情况有关,在这种情况下,我认为不可用的对象实际上存在,可能是因为对它们的活动引用导致没有删除?

谢谢!

4

1 回答 1

0

我想我已经找到了这些问题的答案,并且我想知道......它与垃圾收集器和强引用的使用有关。

理解弱引用文章中说:

如果一个对象可以通过强引用链访问(强可达),则它不符合垃圾回收条件。由于您不希望垃圾收集器破坏您正在处理的对象,这通常正是您想要的

在另一篇文章Gargabe Collection 的工作原理中解释说:

如果一个对象持有另一个对象的引用,并且当您将容器对象的引用设置为 null 时,子对象或包含的对象将自动成为垃圾回收的条件。

所以,我的结论是:

在第一种情况下:当我将活动设置为 null 时detach(),没有内存泄漏,所有对象都可以被垃圾收集,除非适配器具有强引用。所以,我知道除非适配器,否则它包含的活动和所有其他对象都被删除,这是我真正想要的。

在第二种情况下:当我返回容器对象 (A a)onRetainNonConfigurationInstance()并且它具有对 (B b) 的强引用时,b 实例也可以访问,因为它可以通过强引用链访问。

希望这会有所帮助。如果有其他人想发表他/她的意见,将受到欢迎!

于 2012-01-21T13:01:30.377 回答