Android 理解 Fragment 的 setRetainInstance(boolean)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11182180/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 06:14:11  来源:igfitidea点击:

Understanding Fragment's setRetainInstance(boolean)

androidandroid-fragments

提问by Ixx

Starting with the documentation:

从文档开始:

public void setRetainInstance (boolean retain)

Control whether a fragment instance is retained across Activity re-creation (such as from a configuration change). This can only be used with fragments not in the back stack. If set, the fragment lifecycle will be slightly different when an activity is recreated:

  • onDestroy() will not be called (but onDetach() still will be, because the fragment is being detached from its current activity).
  • onCreate(Bundle) will not be called since the fragment is not being re-created.
  • onAttach(Activity) and onActivityCreated(Bundle) will still be called.

public void setRetainInstance(布尔保留)

控制是否在 Activity 重新创建期间保留片段实例(例如来自配置更改)。这只能用于不在后堆栈中的片段。如果设置,则重新创建活动时片段生命周期将略有不同:

  • onDestroy() 不会被调用(但 onDetach() 仍然会被调用,因为片段正在与其当前活动分离)。
  • 由于没有重新创建片段,因此不会调用 onCreate(Bundle)。
  • onAttach(Activity) 和 onActivityCreated(Bundle) 仍然会被调用。

I have some questions:

我有一些问题:

  • Does the fragment also retain its view, or will this be recreated on configuration change? What exactly does "retained" mean?

  • Will the fragment be destroyed when the user leaves the activity?

  • Why doesn't it work with fragments on the back stack?

  • Which are the use cases where it makes sense to use this method?

  • 片段是否也保留其视图,还是会在配置更改时重新创建?“保留”究竟是什么意思?

  • 当用户离开活动时片段会被销毁吗?

  • 为什么它不适用于后堆栈上的片段?

  • 哪些用例可以使用此方法?

回答by Alex Lockwood

First of all, check out my poston retained Fragments. It might help.

首先,查看关于保留片段的帖子。它可能会有所帮助。

Now to answer your questions:

现在回答您的问题:

Does the fragment also retain its viewstate, or will this be recreated on configuration change - what exactly is "retained"?

片段是否也保留其视图状态,还是会在配置更改时重新创建 - 究竟什么是“保留”?

Yes, the Fragment's state will be retained across the configuration change. Specifically, "retained" means that the fragment will notbe destroyed on configuration changes. That is, the Fragmentwill be retainedeven if the configuration change causes the underlying Activityto be destroyed.

是的,Fragment的状态将在配置更改期间保持不变。具体来说,“保留”意味着片段不会在配置更改时被破坏。也就是说,即使配置更改导致底层被破坏,Fragment也会保留Activity

Will the fragment be destroyed when the user leaves the activity?

当用户离开活动时片段会被销毁吗?

Just like Activitys, Fragments may be destroyed by the system when memory resources are low. Whether you have your fragments retain their instance state across configuration changes will have no effect on whether or not the system will destroy the Fragments once you leave the Activity. If you leave the Activity(i.e. by pressing the home button), the Fragments may or may not be destroyed. If you leave the Activityby pressing the back button (thus, calling finish()and effectively destroying the Activity), all of the Activitys attached Fragments will also be destroyed.

就像Activitys一样,Fragment当内存资源不足时,s 可能会被系统销毁。您是否让片段在配置更改时保留其实例状态不会影响系统是否会在Fragment您离开Activity. 如果您离开Activity(即通过按主页按钮),则Fragments 可能会也可能不会被销毁。如果您Activity通过按后退按钮离开s (因此,调用finish()并有效地销毁了Activity),所有Activity附加的Fragments 也将被销毁。

Why doesn't it work with fragments on the back stack?

为什么它不适用于后堆栈上的片段?

There are probably multiple reasons why it's not supported, but the most obvious reason to me is that the Activityholds a reference to the FragmentManager, and the FragmentManagermanages the backstack. That is, no matter if you choose to retain your Fragments or not, the Activity(and thus the FragmentManager's backstack) will be destroyed on a configuration change. Another reason why it might not work is because things might get tricky if both retained fragments andnon-retained fragments were allowed to exist on the same backstack.

不支持它的原因可能有多种,但对我来说最明显的原因是Activity持有对 的引用FragmentManager,并且FragmentManager管理后台堆栈。也就是说,无论您是否选择保留您的Fragments ,Activity(以及FragmentManager的 backstack)都将在配置更改时被销毁。它可能不起作用的另一个原因是,如果允许保留片段非保留片段存在于同一个 backstack 中,事情可能会变得棘手。

Which are the use cases where it makes sense to use this method?

哪些用例可以使用此方法?

Retained fragments can be quite useful for propagating state information — especially thread management — across activity instances. For example, a fragment can serve as a host for an instance of Threador AsyncTask, managing its operation. See my blog poston this topic for more information.

保留的片段对于跨活动实例传播状态信息(尤其是线程管理)非常有用。例如,片段可以作为Thread或实例的主机AsyncTask,管理其操作。有关更多信息,请参阅关于此主题的博客文章

In general, I would treat it similarly to using onConfigurationChangedwith an Activity... don't use it as a bandaid just because you are too lazy to implement/handle an orientation change correctly. Only use it when you need to.

在一般情况下,我将其视为类似于使用onConfigurationChangedActivity...不使用它作为一个创可贴只是因为你懒得实现/正确处理的方向变化。仅在需要时使用它。

回答by suitianshi

setRetaininstanceis only useful when your activityis destroyed and recreated due to a configuration change because the instances are saved during a call to onRetainNonConfigurationInstance. That is, if you rotate the device, the retained fragments will remain there(they're not destroyed and recreated.) but when the runtime kills the activity to reclaim resources, nothing is left. When you press back button and exit the activity, everything is destroyed.

setRetaininstance仅在您activity因配置更改而被销毁和重新创建时才有用,因为实例是在调用onRetainNonConfigurationInstance. 也就是说,如果您旋转设备,保留的片段将保留在那里(它们不会被破坏和重新创建。)但是当运行时终止活动以回收资源时,什么也没有留下。当您按下后退按钮并退出活动时,一切都会被破坏。

Usually I use this function to saved orientation changing Time.Say I have download a bunch of Bitmaps from server and each one is 1MB, when the user accidentally rotate his device, I certainly don't want to do all the download work again.So I create a Fragmentholding my bitmaps and add it to the manager and call setRetainInstance,all the Bitmaps are still there even if the screen orientation changes.

通常我使用这个功能来保存方向改变时间。假设我从服务器下载了一堆位图,每个是1MB,当用户不小心旋转他的设备时,我当然不想再做所有的下载工作。所以我创建了一个Fragment保存我的位图并将其添加到管理器并调用setRetainInstance,即使屏幕方向发生变化,所有位图仍然存在。

回答by Kejun Xia

SetRetainInstance(true) allows the fragment sort of survive. Its members will be retained during configuration change like rotation. But it still may be killed when the activity is killed in the background. If the containing activity in the background is killed by the system, it's instanceState should be saved by the system you handled onSaveInstanceState properly. In another word the onSaveInstanceState will always be called. Though onCreateView won't be called if SetRetainInstance is true and fragment/activity is not killed yet, it still will be called if it's killed and being tried to be brought back.

SetRetainInstance(true) 允许片段继续存在。其成员将在配置更改(如旋转)期间保留。但是当活动在后台被杀死时,它仍然可能被杀死。如果后台包含的活动被系统杀死,它的 instanceState 应该由您正确处理 onSaveInstanceState 的系统保存。换句话说, onSaveInstanceState 将始终被调用。尽管如果 SetRetainInstance 为 true 并且片段/活动尚未被杀死,则不会调用 onCreateView ,但如果它被杀死并试图被带回,它仍然会被调用。

Here are some analysis of the android activity/fragment hope it helps. http://ideaventure.blogspot.com.au/2014/01/android-activityfragment-life-cycle.html

以下是对android活动/片段的一些分析,希望对您有所帮助。 http://ideaventure.blogspot.com.au/2014/01/android-activityfragment-life-cycle.html

回答by Gastón Saillén

setRetainInstance() - Deprecated

setRetainInstance() - 已弃用

As Fragments Version 1.3.0-alpha01

作为片段版本 1.3.0-alpha01

The setRetainInstance() method on Fragments has been deprecated. With the introduction of ViewModels, developers have a specific API for retaining state that can be associated with Activities, Fragments, and Navigation graphs. This allows developers to use a normal, not retained Fragment and keep the specific state they want retained separate, avoiding a common source of leaks while maintaining the useful properties of a single creation and destruction of the retained state (namely, the constructor of the ViewModel and the onCleared() callback it receives).

Fragments 上的 setRetainInstance() 方法已被弃用。随着 ViewModel 的引入,开发人员拥有一个特定的 API 来保留可以与活动、片段和导航图相关联的状态。这允许开发人员使用一个普通的、不保留的 Fragment 并将他们想要保留的特定状态分开,避免常见的泄漏源,同时保持单个创建和销毁保留状态(即 ViewModel 的构造函数)的有用属性和它接收的 onCleared() 回调)。

回答by Marian Pa?dzioch

setRetainInstance(boolean)is useful when you want to have some component which is not tied to Activity lifecycle. This technique is used for example by rxloaderto "handle Android's activity lifecyle for rxjava's Observable" (which I've found here).

setRetainInstance(boolean)当你想要一些与 Activity 生命周期无关的组件时很有用。例如,rxloader使用此技术“为 rxjava 的 Observable 处理 Android 的活动生命周期”(我已在此处找到)。