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
Understanding Fragment's setRetainInstance(boolean)
提问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 Fragment
will be retainedeven if the configuration change causes the underlying Activity
to be destroyed.
是的,Fragment
的状态将在配置更改期间保持不变。具体来说,“保留”意味着片段不会在配置更改时被破坏。也就是说,即使配置更改导致底层被破坏,Fragment
也会保留Activity
。
Will the fragment be destroyed when the user leaves the activity?
当用户离开活动时片段会被销毁吗?
Just like Activity
s, Fragment
s 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 Fragment
s once you leave the Activity
. If you leave the Activity
(i.e. by pressing the home button), the Fragment
s may or may not be destroyed. If you leave the Activity
by pressing the back button (thus, calling finish()
and effectively destroying the Activity
), all of the Activity
s attached Fragment
s will also be destroyed.
就像Activity
s一样,Fragment
当内存资源不足时,s 可能会被系统销毁。您是否让片段在配置更改时保留其实例状态不会影响系统是否会在Fragment
您离开Activity
. 如果您离开Activity
(即通过按主页按钮),则Fragment
s 可能会也可能不会被销毁。如果您Activity
通过按后退按钮离开s (因此,调用finish()
并有效地销毁了Activity
),所有Activity
附加的Fragment
s 也将被销毁。
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 Activity
holds a reference to the FragmentManager
, and the FragmentManager
manages the backstack. That is, no matter if you choose to retain your Fragment
s 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
管理后台堆栈。也就是说,无论您是否选择保留您的Fragment
s ,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 Thread
or AsyncTask
, managing its operation. See my blog poston this topic for more information.
保留的片段对于跨活动实例传播状态信息(尤其是线程管理)非常有用。例如,片段可以作为Thread
或实例的主机AsyncTask
,管理其操作。有关更多信息,请参阅我关于此主题的博客文章。
In general, I would treat it similarly to using onConfigurationChanged
with 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.
在一般情况下,我将其视为类似于使用onConfigurationChanged
与Activity
...不使用它作为一个创可贴只是因为你懒得实现/正确处理的方向变化。仅在需要时使用它。
回答by suitianshi
setRetaininstance
is only useful when your activity
is 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 Fragment
holding 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 的活动生命周期”(我已在此处找到)。