ChatGPT解决这个技术问题 Extra ChatGPT

为什么使用 Fragment#setRetainInstance(boolean)?

我发现 Fragment#setRetainInstance(true) 令人困惑。这是从 Android Developer API 中提取的 Javadoc:

public void setRetainInstance (boolean retain) 控制是否在 Activity 重新创建时(例如从配置更改)保留片段实例。这只能与不在后台堆栈中的片段一起使用。如果设置,片段生命周期将在重新创建活动时略有不同:不会调用 onDestroy() (但仍然会调用 onDetach(),因为片段正在与其当前活动分离)。 onCreate(Bundle) 不会被调用,因为片段没有被重新创建。 onAttach(Activity) 和 onActivityCreated(Bundle) 仍将被调用。

问题:作为开发人员,您如何使用它,为什么它会让事情变得更容易?

具有良好信息的类似问题:Understanding Fragment's setRetainInstance(boolean)
如果设备内存不足,将调用 onDestroy()

C
CommonsWare

作为开发人员,您如何使用它

呼叫 setRetainInstance(true)。我通常在 onCreateView()onActivityCreated() 中使用它。

为什么它让事情变得更容易?

它往往比 onRetainNonConfigurationInstance() 更简单地处理跨配置更改(例如,将设备从纵向旋转到横向)的数据保留。未保留的片段在配置更改时被销毁并重新创建;保留的片段不是。因此,那些保留的片段所持有的任何数据都可用于配置更改后的活动。


@CommonsWare - 如果您在 Activity 中创建新片段并且重新创建了该 Activity,如何避免再次创建新片段?
@Neil:查看片段是否存在(例如,findFragmentById())。如果它存在,请不要重新创建它。
@androiddeveloper:“如果片段持有它的视图以便它不必重新创建它们(在 onCreate() 方法中),它可能需要一些内存” - 欢迎您尝试重新设置小部件进入新活动,但我对此的运气为零。 AFAIK,您需要在 onCreateView() 中重新创建小部件。 “但是,我认为在这个任务中使用 softReference/weakReference 是可以的,对吧?” ——什么任务?
@e.shishkin:应该是。我很少在片段中实现onCreate(),所以我没有尝试过。
@e.shishkin 您可以随时调用它。从技术上讲,您甚至不需要在生命周期方法中调用它(尽管这通常不是您想要/需要做的事情)。
D
DeeV

这对于保持长时间运行的资源(例如套接字)打开非常有帮助。拥有一个包含对蓝牙套接字的引用的无 UI 片段,当用户翻转手机时,您不必担心重新连接它们。

它还可以方便地保留对需要很长时间才能加载的资源的引用,例如位图或服务器数据。加载一次,将其保存在保留的片段中,当活动重新加载时,它仍然存在,您不必重建它。


好的。但是如果我们需要刷新它们呢?
我认为这是某种单身人士通常会做的事情,我错了吗?
@rupinderjeet 是的。 Singleton 是另一种实现方式。单例被认为是“反模式”,有些人对使用它们犹豫不决。片段还具有与活动生命周期相关联的优势,因此您可以获得生命周期事件。例如,如果用户离开应用程序,您可以销毁资源(这也可以使用 Singleton 完成,但需要更多代码)。
R
Ryan M

很晚才添加这个答案,但我认为它会让事情变得更清楚。跟我说。当 setRetainInstance 为:

错误的

片段在配置更改时重新创建。新实例已创建。

所有生命周期方法都会在配置更改时调用,包括 onCreate() 和 onDestroy()。

真的

配置更改时不会重新创建片段。使用相同的实例。

所有生命周期方法都在配置更改时调用,APART FROM onCreate() 和 onDestroy()。

添加到后台堆栈时,保留实例将不起作用。

不要忘记,上述内容适用于 DialogFragment 以及 Fragments。


您可以添加对 Retaining an instance will not work when added to the backstack. ? 的引用吗
如果片段被添加到后台堆栈,如何恢复片段的状态? savedInstanceState 为空,我不能使用 setRetainInstance ...
D
Darish

不推荐使用 setRetainInstance(boolean) 方法,请改用 ViewModels。

Fragments 上的 setRetainInstance(boolean) 方法从 Fragments API 的版本 1.3.0 开始是 deprecated

随着 ViewModels 的引入,开发人员可以使用特定的 API 来保留可与活动、片段和导航图相关联的状态。这允许开发人员使用正常的、未保留的 Fragment 并将他们想要保留的特定状态分开。

这确保了开发人员对这些 Fragment 有一个更易于理解的生命周期(匹配所有其余 Fragment 的生命周期),同时保持单次创建和单次销毁的有用属性(在这种情况下,ViewModel 的构造函数和ViewModelonCleared() 回调)。