何时片段不附加到活动而仅附加到上下文?

Posted

技术标签:

【中文标题】何时片段不附加到活动而仅附加到上下文?【英文标题】:When is a fragment not attatched to an activity but only a context? 【发布时间】:2021-09-16 10:48:52 【问题描述】:

the docs for Fragment.getActivity() 上面写着:Return the FragmentActivity this fragment is currently associated with. May return null if the fragment is associated with a Context instead.

但是片段怎么能不与活动关联呢?我的意思是,我不是总是需要一个 Activity 来在 android 中显示任何内容吗?

【问题讨论】:

【参考方案1】:

片段不是必需FragmentActivity 关联的。相反,它们实际上与 FragmentController 相关联,FragmentActivity 恰好代表您创建和管理,在创建、启动托管活动等时调用适当的调度方法。

这种间接级别是 Facebook 的聊天头(显示由 Service 管理的 Window)如何能够重用 FragmentActivity 使用的相同 Fragment 实例以及 building Navigation apps for Android Automotive(使用CarAppService 显示汽车应用程序)允许您还重复使用片段。

当然,如果您的片段总是从您的一个活动中创建,那么,是的,您绝对可以假设requireActivity() 将在任何时候返回FragmentActivity isAdded() 返回@ 987654334@ - 即在onAttach()onDetach() 之间。这确实包括在生命周期方法中,例如 onViewCreated() 或与您的 Fragment 视图相关的任何内容(例如 OnClickListener)。

【讨论】:

这正是我想要的。因此,在预期的生命周期阶段之间是安全的如果您仅从活动中使用它。除非您明确这样做,否则框架不会将其附加到无 Activity 上下文。【参考方案2】:

1- "... 调用 requireActivity() ... 真的安全吗?" 不,从方法的实现可以看出:

/**
 * Return the @link FragmentActivity this fragment is currently associated with.
 *
 * @throws IllegalStateException if not currently associated with an activity or if associated
 * only with a context.
 * @see #getActivity()
 */
@NonNull
public final FragmentActivity requireActivity() 
    FragmentActivity activity = getActivity();
    if (activity == null) 
        throw new IllegalStateException("Fragment " + this + " not attached to an activity.");
    
    return activity;

如果活动为空,此方法将引发异常,如果您没有处理此异常,因为您可能没有处理 getActivity() 的空值,应用程序将崩溃。编译器不会仅仅因为此方法中有一个空检查而显示警告。

2- “但是片段怎么能不与活动相关联?我的意思是,我不是总是需要一个活动来在Android中显示任何东西吗?” 真的。一个附加的片段需要一个活动,但是,仅仅因为调用了 getActivity() 方法并不意味着它的片段处于附加状态。因此,它可能发生在侦听器或某些回调中,可能会在活动被销毁时调用 getActivity(),例如。由于旋转。由于这种情况,您应该通过 getActivity() 检查返回值的无效性。当活动被销毁时,关联上下文不是活动的上下文。关于这个问题有几个有趣的见解和很好的建议,你可以在这里阅读:getActivity() returns null in Fragment。

【讨论】:

我知道requireActivity() 可以抛出异常。问题是,在生命周期的哪些阶段,我们可以保证它不会抛出异常?如果没有,则该方法将不存在。有时您想使用附加活动中父布局中的值来调整视图填充。您不想多次修改填充,但也不想在 if 语句中调用代码,因为那样可能会丢失。 在 onAttach 和 onDetach 之间是安全的。在其他生命周期方法中,您可以根据需要编写代码,只需在获取活动时检查 null。 请阅读链接以获得更简洁和详细的解决方案。 “你在 onAttach 和 onDetach 之间是安全的” - 但是为什么 Google 最近弃用了onAttach(Activity),告诉我们使用onAttach(Context)?对我来说,这听起来像 onAttach(Context) 可以被调用,即使没有活动,只是一个上下文。但为什么?我错过了什么? 在 onAttach(Context) 中,如果该上下文属于活动,则附加片段,并且您可以期望调用其他生命周期方法。但是,如果不是,onDetach 将立即被调用。尽管如此,您仍应检查是否为 null,因为如果在 onDetach 之后侦听器或回调调用 getActivity 它会为 null。但是如果 onAttach 被调用而 onDetach 没有被调用,getActivity 将不会返回 null。【参考方案3】:

“但是片段怎么能不与活动关联呢?” - 您始终可以创建片段的实例,而无需将其附加到任何活动。但是,如果您不将其附加到活动,它就不会显示在屏幕上(即生命周期方法不会启动)。这是一个interesting thread 来阅读。

“我的意思是,我不是总是需要 一个 Activity 来显示 Android 中的任何内容吗?” - 是的。

我发现这个google developer training 链接对于理解活动和片段之间的生命周期回调非常有用。在此处引用该链接。

Activity 的每个生命周期回调都会产生一个类似的回调 对于每个 Fragment,如下表所示。例如,当 Activity 接收到 onPause(),它会触发一个 Fragment onPause() Activity 中的每个 Fragment。

此外,@Sina 在他的回答中发布的 SO 链接对您可能期望 getActivity 何时返回 null 有一些见解。

【讨论】:

以上是关于何时片段不附加到活动而仅附加到上下文?的主要内容,如果未能解决你的问题,请参考以下文章

片段未附加到上下文 - 延迟的 UI 更改

java.lang.IllegalStateException:未附加到上下文的片段

如何重新附加片段(片段未附加到活动 Kotlin)

片段未附加到我的活动

java.lang.IllegalStateException:片段未附加到活动

Android在活动视图中附加片段获取片段已添加错误