理解Fragment的setRetainInstance(boolean)

探讨了Android中Fragment的setRetainInstance方法的作用,解释了在配置改变时如何保留Fragment状态,包括其应用场景和限制条件,如与Activity生命周期的关系及为何不适用于后栈中的Fragment。

本文翻译自:Understanding Fragment's setRetainInstance(boolean)

Starting with the documentation: 从文档开始:

public void setRetainInstance (boolean retain) 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). onDestroy()不会被调用(但是onDetach()仍然会被调用,因为片段正在与其当前活动分离。
  • onCreate(Bundle) will not be called since the fragment is not being re-created. 因为片段没有被重新创建,所以不会调用onCreate(Bundle)。
  • onAttach(Activity) and onActivityCreated(Bundle) will still be called. 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? 哪个是使用此方法有意义的用例?


#1楼

参考:https://stackoom.com/question/kuzk/理解Fragment的setRetainInstance-boolean


#2楼

First of all, check out my post on retained Fragments. 首先,查看关于保留碎片的帖子 It might help. 它可能有所帮助。

Now to answer your questions: 现在回答你的问题:

Does the fragment also retain its view state, or will this be recreated on configuration change - what exactly is "retained"? 片段是否也保留其视图状态,或者是否会在配置更改时重新创建 - 究竟是什么“保留”?

Yes, the Fragment 's state will be retained across the configuration change. 是的, Fragment的状态将在配置更改中保留。 Specifically, "retained" means that the fragment will not be destroyed on configuration changes. 具体而言,“保留”意味着在配置更改时不会破坏该片段。 That is, the Fragment will be retained even if the configuration change causes the underlying Activity to be destroyed. 也就是说,即使配置更改导致底层Activity被销毁, Fragment也会被保留

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. 就像Activity s一样,当内存资源不足时,系统可能会破坏Fragment 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 . 在您离开Activity ,是否让碎片在配置更改中保留其实例状态不会影响系统是否会破坏Fragment If you leave the Activity (ie by pressing the home button), the Fragment s may or may not be destroyed. 如果您离开Activity (即按下主页按钮),可能会或可能不会销毁Fragment 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 (因此,调用finish()并有效地销毁Activity ),所有Activity附加的Fragment也将被销毁。

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. 可能有多种原因导致它不受支持,但最明显的原因是Activity包含对FragmentManager的引用,而FragmentManager管理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. 也就是说,无论您是否选择保留FragmentActivity (以及FragmentManager的Backstack)都将在配置更改时被销毁。 Another reason why it might not work is because things might get tricky if both retained fragments and non-retained fragments were allowed to exist on the same 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. 例如,片段可以充当ThreadAsyncTask实例的主机,从而管理其操作。 See my blog post on this topic for more information. 有关详细信息,请参阅关于此主题的博客文章

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. 一般来说,我会把它与使用onConfigurationChangedActivity一样对待...不要仅仅因为你太懒而无法正确实现/处理方向更改而将其用作onConfigurationChanged Only use it when you need to. 只在需要时使用。


#3楼

SetRetainInstance(true) allows the fragment sort of survive. SetRetainInstance(true)允许片段生存。 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. 如果后台中的包含活动被系统杀死,那么它的instanceState应该由您在onSaveInstanceState上正确处理的系统保存。 In another word the onSaveInstanceState will always be called. 换句话说,将始终调用onSaveInstanceState。 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且片段/活动尚未被杀死,则不会调用onCreateView,但如果它被杀死并被试图被带回,它仍然会被调用。

Here are some analysis of the android activity/fragment hope it helps. 以下是对android活动/片段的一些分析希望它有所帮助。 http://ideaventure.blogspot.com.au/2014/01/android-activityfragment-life-cycle.html http://ideaventure.blogspot.com.au/2014/01/android-activityfragment-life-cycle.html


#4楼

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 . setRetaininstance仅在由于配置更改而销毁和重新创建activity时才有用,因为在调用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. 当您按下后退按钮并退出活动时,一切都将被销毁。

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


#5楼

setRetainInstance(boolean) is useful when you want to have some component which is not tied to Activity lifecycle. 当您想要一些与Activity生命周期无关的组件时, setRetainInstance(boolean)非常有用。 This technique is used for example by rxloader to "handle Android's activity lifecyle for rxjava's Observable" (which I've found here ). 这种技术例如由rxloader用于“处理Android的rxjava的Observable的活动生命周期”(我在这里找到)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值