Android碎片中的getActivity() = null

14

我在我的应用程序中使用了碎片。而在使用它们时非常普遍的问题是当使用getActivity()时会出现NPE(NullPointerException)。我知道我们可以通过每次检查getActivity() != null或检查片段是否isAdded()来解决它。

在我的某个类中,我在60多个地方获取活动的上下文。在所有这些地方检查getActivity()不是空或片段仍添加到活动中,使代码变得丑陋、更长且难以维护。有没有其他方法来处理这个问题?甚至在从活动中删除片段时销毁片段(并停止它正在进行的任何工作)是否可能?

此方式是否建议使用?

5个回答

13

根据我的经验,大多数getActivity()返回null的情况都出现在异步回调中。

例如,你的fragment触发了一个AsyncTask,然后在后台任务完成之前就被移除了,当后台任务完成并在onPostExecute()中调用getActivity()时,它会得到一个null,因为该fragment已经从activity中分离。

我的解决方案:

1.在每个异步回调的开始处检查getActivity()==null,如果是这种情况,那么就终止该方法。

2.在onDetach()中取消异步任务。

我认为这比在onAttach()中保存activity实例更好,因为既然你的fragment已经被移除了,在大多数情况下,为什么还要做剩下的回调工作(大多数是UI代码)呢?


1
对我来说,这似乎是最好的解决方案! - LoveMeSomeFood
非常好的解决方案!此解释并不明显!好观点! - JarsOfJam-Scheduler
哇...这个答案是最好的。在我的情况下,getActivity()有时会返回null,我不知道什么时候会返回null以及如何处理它。感谢@handhand,我意识到在我的代码中,getActivity()位于异步工作的OkHttp回调中。此外,当getActivity()为null时,我不需要做任何事情,因为Activity和相关的Fragments已经不存在了。 - mazend

4

在onActivityCreated()方法中,getActivity将被重新初始化。

因此,根据片段的生命周期http://developer.android.com/guide/components/fragments.html,在onActivityCreated()之后立即调用getActivity()更加安全。例如,在onStart()中调用,这样它永远不会为null,无需执行无用的检查,如isAdded和getActivity != null。

附:如果我们使用该解决方案:

@Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        mActivity = activity;
    }

mActivity永远不会为空 - 但是在onActivityCreated()方法中,getActivity()会变得与mActivity不同。 我的意见 - 当然我们可以将整个activity保存在变量中,但按照Android片段的生命周期工作流程,在onActivityCreated()之后正确获取activity更为安全。


如果你的片段是静态的,那么可能会出现内存泄漏问题,我个人也遇到过这个问题。永远不要在片段中收集活动引用。如果这样做,请在onDetach()中强制将其标记为null。 - silentsudo
没错,即使它不是静态的,关于activity这一点也是合理的。而且我从来不使用静态fragments - 它太危险了(就像你说的那样-内存泄漏),也从来没有看到过它有用的情况。 - Alexey O.

0
我的解决方案是在BaseActivity中重写onSaveInstanceState方法:
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    //solution of fragment.getActivity() is null
    outState.remove("android:support:fragments");
}

0

我认为你应该使用FragmentonAttach(Activity)方法。

我认为那应该帮助你避免所有这些NPE。


如果我在UI加载时使用它并删除片段,仍不会导致NPE吗? - LoveMeSomeFood
@Rani 可以使用引用来进行活动,并检查它是否为空,并确保在 onDetach 中将其标记为 null。 - silentsudo

-1

我没有找到解决方案,可能是因为如果你考虑片段的生命周期,你应该能够理解何时检查空值。


1
是的,我明白分离的片段仍然存在:( 我希望有某种方法!! - LoveMeSomeFood
1
我明白你的意思。基本上,当我完成异步操作并且想要确保片段仍附加到活动时(例如检查是否已添加http://developer.android.com/reference/android/app/Fragment.html#isAdded()),我倾向于检查我的活动/上下文。但是,如果您在链接页面的中间或末尾滚动,您将找到如何协调这两个“不同”的生命周期的方法。 - Simone Casagranda
抱歉,我不明白你在最后一行说的是什么。 - LoveMeSomeFood

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接