保存/恢复Activity和Fragment状态的最佳实践(译)

几个月以前,我发布了一篇关于Fragment状态保存和恢复的文章,那可能是目前为止最好的方式用于保存/恢复 Android Fragment 的状态。我收到了很多来自世界各地的Android开发者有价值的反馈。十分感谢你们 =)
无论如何,StatedFragment打破了设计模式,我使用了不同于Android状态保存/恢复的方式来设计它,这样做的目的是为了让Android开发者能够更简单的理解Fragment状态的保存与恢复,就像Activity做的一样(同时处理View状态和实例状态)。

所以我通过开发StatedFragment做了一个实验,并且看看它是怎么做的,看看StatedFragment这样的设计是否更容易被理解?是否对开发者更加友好?

现在,两个月的实验过去了,我相信我已经得到了结果。虽然 StatedFragment 有点容易被理解,但是它同时带来了很大的问题。它破坏了Android View的基本框架.所以我认为它这是很糟糕的,可能会导致长远的影响。事实上我已经对自己的代码感到担忧了... 由于这个原因,我决定从现在开始弃用StatedFragment。并且,为了弥补我错误,我写了这篇文章,用可见动图的方式来展示基于Android的设计如何保存和恢复Fragment的状态的最佳实践。


理解在Activity的状态被保存/恢复的时候发生了什么

当Activity的onSaveInstanceState被调用的时候,Activity将会从View 层次(View Hierachy)中的每一个View中自动搜集View的状态。请注意,只会搜集实现了View状态保存/恢复的内部方法的View的数据。一旦onRestoreInstanceState被调用,Activity将会将这些搜集到的数据一对一的返还给View 层次里在搜集的时候提供了同样的android:id属性的View。

这就是为什么尽管Activity已经被销毁,而我们并没有做一些特别的事情来保存状态,但是EditText中键入的文本仍然能够呈现的原因。这并不是什么魔法,这些View 的状态已经被自动的保存和恢复回来了。

这也是为什么View 在没有被设置android:id属性的时候不能保存和恢复自己的状态的原因。

尽管这些View 的状态被自动的保存了,但是Activity的成员变量并不会有同样的效果。这些成员变量会被和Activity一起销毁。你可以手动的保存和恢复它们,通过onSaveInstanceStateonRestoreInstanceState方法。


让我们看看。





















这就是为什么尽管Activity已经被销毁,而我们并没有做一些特别的事情来保存状态,但是EditText中键入的文本仍然能够呈现的原因。这并不是什么魔法,这些View 的状态已经被自动的保存和恢复回来了。

这也是为什么View 在没有被设置android:id属性的时候不能保存和恢复自己的状态的原因。

尽管这些View 的状态被自动的保存了,但是Activity的成员变量并不会有同样的效果。这些成员变量会被和Activity一起销毁。你可以手动的保存和恢复它们,通过onSaveInstanceStateonRestoreInstanceState方法。




这就是为了恢复Activity实例的状态和View 状态需要做的。

理解在Fragment的状态被保存/恢复的时候发生了什么

如果Fragment被系统销毁,所有事情都会发生的像Activity发生的那样。

这意味着每一个单独的成员变量被销毁了。你必须分别地通过 onSaveInstanceStateonActivityCreated方法,手动的保存和恢复这些变量。 请注意在Fragment里面没有 onRestoreInstanceState方法存在。


对于Fragment来说,有一些特殊情况不同于Activity,我觉得你需要知道这些情况。一旦Fragment从后退栈中返回,它的View 会被销毁,并重新创建



这这种情况下,Fragment并不会被销毁,只有Fragment中的View 会被销毁。结果是,并不会发生任何实例状态的保存。那上面展示在Fragment生命周期重新创建View的时候发生了什么?

别惊讶,因为Android是这样设计的。在这种情况下,Fragment中的View 状态的保存/恢复会被内部调用。结果就是,每一个实现了内部View 状态保存/恢复的View ,将会被自动的保存并且恢复状态,例如带有android:freezeText="true"属性的EditText或者TextView。就像之前完美显示的一样。


请注意,在这种情况下,只有View 被销毁(并重建)了。Fragment不会被销毁,就像它内部的成员变量一样。所以你不需要对它们做任何事情,不需要任何额外的代码。


你也许已经注意到了,如果Fragment中的每一个View 都在内部实现了View 的状态的保存和恢复。在这种情况下,你就没有必要做任何事情,View 状态会被自动的恢复,并且Fragment中的成员变量也和之前的一样。

所以Fragment状态保存/恢复最佳实践的第一条件就是...

应用中使用的每一个单独的View都必须在内部实现状态的保存和恢复

Android内部通过onSaveInstanceState 和 onRestoreInstanceState 方法提供了保存和恢复View 状态的机制。开发者的任务就是实现它。



基本上来说,每一个单独的Android提供的的标准View 组件都已经在内部完成了这些事情,例如EditText,TextView,Checkbox. 尽管你需要手动让它生效,比如,你需要为TextView设置android:freezeText为true,来使用这个功能。

但是如果我们讨论关于互联网上贡献的第三方的自定义组件。我必须说,它们大多数都没有实现这部分的代码,这在使用中会导致很大的问题。

如果你决定使用第三方的自定义组件,你不得不确保它已经在内部实现了View 的保存和恢复,否则你必须创建继承这个三方组件的一个派生的子类,并且自己实现onSaveInstanceStateonRestoreInstanceState方法。




并且,如果你创建你自己的自定义View或者自定义ViewGroup,也不要忘记实现这两个方法。应用中每一个类型的View实现这部分都是很重要的。

还有,不要忘记为每一个你需要开启View状态保存和恢复的View设置android:id属性,不然它们的状态不能正确的恢复。




这篇文章已经进行到了一半!

完全分开处理Fragment状态和view状态

为了使你的代码变得干净和可扩展,你最好把Fragment状态和View状态分开处理。如果这里有任何属性是属于View的,在View内部进行保存和恢复.如果这里有任何属性是属于Fragment的,在Fragment内部进行保存和恢复。这里有一个例子。





让我再重复一遍

不要在Fragment中的 onSaveInstanceState 中保存View状态!!!

不要在Fragment中的 onSaveInstanceState 中保存View状态!!!

不要在Fragment中的 onSaveInstanceState 中保存View状态!!!

反之亦然。

以上就是本篇文章所有的内容了,是一篇关于如何保存和恢复Activity,Fragment和View状态的最佳实践,希望你在这篇文章中找到一些有用的信息=)

再见StatedFragment,迎接NestedActivityResultFragment

请按照上面所描述的方法来保存恢复Activity,Fragment,View的状态。从现在开始,让我把StatedFragment废弃掉吧。

还有,StatedFragment中获取onActivityResult的特性在NestedFragment中仍然是可以使用的。为了避免未来的混淆,我决定把这个功能分离到NestedActivityResultFragment这个新的类里面,在v0.10.0以及后续的版本可用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值