【问题标题】:What is the purpose of fragment recycling by FragmentManager in Android?Android中FragmentManager进行片段回收的目的是什么?
【发布时间】:2024-01-21 20:20:01
【问题描述】:

我知道第一次使用片段时应该使用FragmentTransaction创建Fragment并将其添加到管理器中。但后来在屏幕旋转等配置更改后,可以通过findFragmentByIdfindFragmentbyTag找到。

但是在屏幕旋转时,我发现片段onAttachonCreateonCreateViewonStartonResume的构造函数和所有回调方法都被再次调用了,即使片段是从findFragmentByTag 返回,没有显式调用构造函数。

构造函数被调用的事实意味着片段对象可以被垃圾收集。那么片段的哪一部分实际上存储在配置更改上?如果fragment对象被垃圾回收并重新创建,那么回收它的目的是什么?

【问题讨论】:

    标签: android fragment fragmenttransaction fragmentmanager


    【解决方案1】:

    片段没有被回收。如果您在屏幕定向后登录Fragment.toString(),您将获得不同的值,这意味着这些片段实例是不同的,是从头开始创建的。所有生命周期方法都称为但是您可以通过onSaveInstanceState(Bundle) 保留一些值。

    这不适用于您调用setRetainInstance(true) 的片段。现在唯一重复的生命周期方法是onCreateViewonViewCreated、(长时间停顿)、onDestroyView。实例相同,保留字段变量。

    编辑:

    Android OS 是否会在宿主 Activity 上调用 onCreate 之前自动销毁和创建 Fragment 并设置相同的 Tag 和 ID?

    TL;DR:是的。

    FragmentState 类字段变量包含有关一个片段的信息,该片段始终保留(以及其他标签和 ID)。

    当你旋转屏幕时,FragmentManagerImpl.restoreAllState(...) 被调用,它要么抓取保留的片段,要么实例化新的片段并将它们重新附加到新的活动。这是Activity.onCreate(Bundle) 的一部分。

    那么片段的哪一部分实际存储在配置更改上?

    如上所述的FragmentState 加上您或框架在onSaveInstanceState(Bundle) 中写入的任何内容。如果片段被标记为保留,则保存视图层次结构以外的所有内容。

    如果fragment对象被垃圾回收并重新创建,那么回收它的目的是什么?

    如果它被销毁并从头开始创建(新实例),它根本不会被回收。您可以保留片段实例 - 相同的实例在屏幕方向更改后仍然存在 - 或保存并恢复实例状态 - 旧片段实例被销毁,新片段实例被创建并填充来自旧实例的一些数据。

    【讨论】:

    • 那么,如何在宿主Activity的onCreate中调用findFragmentByTag来获取片段的引用呢? Android OS 是否会在旋转后在宿主 Activity 上调用 onCreate 之前自动销毁并创建 Fragment 并设置相同的 Tag 和 ID?
    • @jenddy 嗨,请检查更新的答案。简而言之:是的,Activity 能够记住标签和 ID。