【问题标题】:Activity's onDestroy / Fragment's onDestroyView set Null practicesActivity 的 onDestroy / Fragment 的 onDestroyView 设置 Null 做法
【发布时间】:2014-12-09 18:48:43
【问题描述】:

我正在阅读 ListFragment 源代码,我看到了这个实现:

ListAdapter mAdapter;
ListView mList;
View mEmptyView;
TextView mStandardEmptyView;
View mProgressContainer;
View mListContainer;
CharSequence mEmptyText;
boolean mListShown;

/**
 * Detach from list view.
 */
@Override
public void onDestroyView() {
    mHandler.removeCallbacks(mRequestFocus);
    mList = null;
    mListShown = false;
    mEmptyView = mProgressContainer = mListContainer = null;
    mStandardEmptyView = null;
    super.onDestroyView();
}

在此函数中,Google 开发人员将所有在 ListFragment 中声明的视图字段设置为 Null,并删除回调“mRequestFocus”。

ListActivity 源代码中。谷歌开发者实现如下:

protected ListAdapter mAdapter;
protected ListView mList;

private Handler mHandler = new Handler();


@Override
protected void onDestroy() {
    mHandler.removeCallbacks(mRequestFocus);
    super.onDestroy();
}

我没有看到 Google 开发人员在 ListActivity 的 onDestroy 上将 Null 设置为 mList,就像他们为 ListFragment 类所做的那样。

我的问题是

  1. 为什么google开发者在ListActivity的onDestroy中没有将Null设置为mList?有什么原因吗?

  2. 是否需要将Activity的onDestroy和Fragment的onDestroyView中的所有View字段都设置为Null?

3. Activity的onDestroy和Fragment的onDestroyView这两个函数设置Null有什么做法吗?

感谢您的想法!

【问题讨论】:

    标签: android android-activity android-fragments ondestroy


    【解决方案1】:

    所以 Fragment 和 Activities 不同的原因是它们的生命周期不同。当Activity 被销毁时,它会永远消失。但是,Fragments 可能会在实际销毁之前多次创建和销毁它们的视图。为澄清起见,在 Activity 中:

    onDestroy()
    onCreate()
    

    永远不会按顺序发生同一个 Activity 实例。对于 Fragment,以下内容是完全有效的:

    onCreate()
    onCreateView()
    onDestroyView()
    onCreateView()
    onDestroyView()
    onDestroy()
    

    Fragment 进入后台堆栈时,您可以看到这种情况。它的视图将被销毁(因为它不再可见),但是当用户按下返回以返回它时,实例将保留在周围以便轻松恢复(此时将再次调用 onCreateView())。

    onDestroyView() 之后,您可以(并且可能应该)释放您的所有View 引用以允许它们被垃圾回收。在许多情况下,这不是必需的,就像它只是在配置更改期间发生一样,onDestroy() 将立即跟进,整个实例将被垃圾回收。

    从本质上讲,我认为在onDestroyView() 中释放所有视图引用是一种很好的做法,如果您的应用具有较大的后台堆栈,则可以节省相当多的内存。

    【讨论】:

    • 很好的解释。我有个问题。为什么 google 开发者没有在 ListFragment 的 onDestroyView 中将 Null 设置为 mAdapter。不需要将Null设置为mAdapter等非ui字段吗?
    • 这是个好问题。通常这无关紧要,但适配器往往也持有对 Activity 上下文的引用。我想它符合该方法的合同,即onDestroyVIEW,所以他们只是破坏了视图引用。我认为如果你打电话给setListAdapter(),然后你再打电话给getListAdapter(),这将是一种意想不到的行为,这是莫名其妙的null。由于适配器不是一个昂贵的对象来保持(除了在 setRetainInstance() 可能泄漏活动的情况下),释放它并没有太多好处。
    • 我想知道在绑定之前在 oncreateview 中取消绑定是否更好?
    • 当您绑定到onCreateView 中的(子)视图的新实例时,将取消绑定(子)视图的旧实例。在分配新值之前设置null 是不必要的。
    • 在 Kotlin 中,这将使绑定可以为空,从而迫使您将空安全运算符添加到绑定的每个调用中。是否有解决此问题的方法,或者是否只是继续将操作员添加到每个呼叫中​​?
    【解决方案2】:

    如果不影响应用程序的逻辑,则无需设置 null。例如。 if (mList == null) ...

    【讨论】:

    • 不设置Null会导致内存泄漏怎么办?
    • 不可能,因为所有引用都在fragment对象下,也就是说一旦fragment对象出来了,所有的views和其他的也都出来了。
    • @VladimirLichonos 实际上,这很有可能,特别是如果片段上设置了setRetainInstance(true)。如果你保留这些视图引用,你很容易泄漏一个 Activity 实例(因为视图保留了对 Activity 的引用)。
    • 在使用 Views 和 setRetainInstance 时这是一个奇怪的用例。但同样,它是基于我上面提到的片段的逻辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    相关资源
    最近更新 更多