很抱歉上周我由于沉迷代码而忘了发文。android
今天和你们分享的这篇,本来是《重学安卓》付费专栏连载的第三篇,没想到在我这几天业余时间独立开发的小应用《JDGD》中,连续赶上了 7 处 “状态重建” 的场景!网络
考虑到我在 <掘金> 等热门技术社区 发文的目标是,提供 “从 0 到 1”、易于理解和贯通的 摆渡文,致力于为读者拨开迷雾、创建感性认识。数据结构
于是 原味的、硬核的、钻研细节的 文章,我可能是在小众的付费技术社区发布。对此感兴趣的朋友请不要慌,文末连接给出 😉源码分析
JDGD 的页面结构是,最外层由一个 Activity 装载着一个 ContainerFragment,而后 ContainerFragment 中又装载了 3 个 ChildFragment。至关因而个 3 层嵌套页面结构。布局
用户平时能够操做的,就是在这 3 个 ChildFragment 之间来回切换。而且当发生旋转屏幕时,来自 3 个层次的 5 个页面都会发生重建。设计
这要是换作之前的话,我八成是会被难住,由于我司的产品,手机端是固定竖屏,平板端是固定横屏,即便开启了旋转屏幕模式,也不会走重建的流程,于是多年来我都没有钻研过这个问题。3d
而且,网络上关于重建的文章 可能是人云亦云、含糊不清,并无把最关键的细节给讲明白、讲透,致使我最开始也在 半吊子文章中 白费很多时间。cdn
好在上上星期,我亲自复盘和实证了 “状态重建” 的知识点,因而这回赶上的几个问题,都是轻轻松松地获得化解 😉。blog
考虑到页面重建和状态管理,真的是每一个人都必然会遇到的问题,因而我就 破例 地将 Activity 状态重建的知识,无保留地分享给你们。继承
已经付费的小伙伴们请不要担忧,今天仅仅是经过介绍 Activity 的重建,来奠基对重建的认知基础,真正的好戏还在后头 ~
还没阅读过的小伙伴也不要着急,正因为今天讲的是基础,即便只看这篇,你也没有白来!
很高兴见到你!
上一期,我在发表的 《重学安卓:Activity 生命周期的 3 个辟谣》 中,经过介绍网上 99% 的文章都未曾解析过的 “进程模式”,来帮助你们深刻理解 Activity 生命周期 的设计依据、存在乎义 及 注意事项。
而且,文末我还针对网文的 3 个讹传,来给你们辟了谣。
相信通过这样一次介绍,你对生命周期拥有了相比其余人更加深入的认识。😉
那么这一期,咱们来结合现实的案例,来说解一下 Activity 的重建机制。
就在上周五,我司向客户推送了 App 新版本,原觉得万事大吉,毕竟通过了一周的打磨,各项功能都已趋于流畅稳定,没想到,在客户近乎变态的数据操做下,有客户反映 “页面切换巨卡”、“速度巨慢”。
为什么会产生这种状况呢?我找到编写该页面的同事询问了原因。
同事说,问题在于每次 onPause 时,为了不App 切到后台被系统回收致使数据丢失,而作了大量的数据持久化操做。
那为何不直接经过 Activity 的状态管理机制 来管理临时数据呢?
同事说,那东西“不靠谱”,用着感受内心没底。
…… 是网上介绍 Activity 重建流程和状态管理的文章不够多吗?不是的,网文都有提到:当发生重建时,就会走 onSaveInstanceState 和 onRestoreInstanceState,
然而却没有一篇深刻地探究过:当走 onSaveInstanceState 和 onRestoreInstanceState 时,过程当中究竟经历了哪些细节、背后 决定状态被成功保存和恢复的关键条件 究竟是怎样的。
这使得读者在使用这个机制时忐忑不安,没法 100% 肯定不会出事。
因而在通过源码分析和再三的实测检验后,我将 “重建机制” 及 “状态管理机制” 的内容整理成这篇文章。
若是阅读完本文后,你对两者的缘起、规律有了明确的认识,从而 100% 放心地在往后工做中使用,那个人这番功夫就没白费 ~
正常的生命周期流程,是页面从正常建立到销毁全流程。
而重建流程,则是在特定条件下,引起页面被销毁,并再次被建立的流程。
一般是 “系统资源的回收” 或 “配置发生变化” 致使的重建。
划重点 👆 👆 👆
系统资源回收是指:
当 App 处于背景模式时,可能因系统内存不足而被回收。
例如按下 Home 键切回桌面,或是接电话跳转到电话程序,都有可能使此前的这个 App 处于背景模式。
配置发生变化是指:
当系统配置发生变化时,好比屏幕方向、语言的改变。
一来: 对于资源回收的状况,保存状态并等到使用时再恢复,要比后台存留进程 所占的资源要小得多。
二来: 对于配置变化的状况,好比当屏幕方向发生变化时,惟有重建,才有机会加载不一样的视图,若是横竖屏的布局不一样的话。
首先,“状态” 是指支撑 UI 界面内容展现的临时数据。
好比 EditText 中的文本、CheckBox 的勾选与否。
有且只有引起重建时,Activity 会走 onSaveInstanceState 和 onRestoreInstanceState,来保存和恢复状态。
onSaveInstanceState 执行在 onStop 以前,onRestoreInstanceState 执行在 onStart 以后。
其次,Activity 有两个数据结构用于保存状态:
一个是 View States,专门用于存储 View 的状态;
再一个是 Instance States,用于存储 View States 以及 开发者在 onSaveInstanceState 中手动保存的 Activity 成员变量。
在引起重建时,Activity 会自动为咱们保存和恢复 View 的状态。具体表现为:
Activity 在 onSaveInstanceState 时,会 自动收集 View Hierachy 中每个 “实现了状态保存和恢复方法” 的 View 的状态,这些状态数据会在 onRestoreInstanceState 时回传给每个 View。而且回传时是依据 View 的 id 来逐一匹配的。
划重点 👆 👆 👆
其中,View 的状态数据会被收集到 View States 中,View States 也会随着 Activity 中其余被指定收集的成员变量,一同被收集到 Instance States 中,等待恢复时逐个恢复。
简言之:
1.为了成功保存状态,要求在 View 内部实现状态保存和恢复方法。
原生的 View 都有作到;若是是自定义 View,务必记住这一点;若是第三方 View 没作到,能够经过继承其来实现保存和恢复方法。
2.为了成功恢复状态,要求在布局中给 View 赋予相应的 id。
划重点 👆 👆 👆
3.若是是 Activity 的成员变量,须要额外在 Activity(子类)中重写 onSaveInstanceState 和 onRestoreInstanceState 方法。
注意:
Activity 中重写仅仅是为了额外地保存成员变量。重写方法时,记得要保留基类(super)的实现,Activity 正是在基类中完成 View 状态的保存和恢复。
划重点 👆 👆 👆
在清单文件中为该 Activity 配置 android:configChanges 属性。
好比属性值 orientation|screenSize 对应着旋转屏幕,locale 对应着语言变化。
如此,在配置发生变化时,不会致使重建,而是走 onConfigurationChanged 回调。
只要遵循 《状态保存和恢复的的注意事项》一节所提到的关键细节,就能稳妥地保存和恢复状态。
你不再用为了临时数据而在 onPause 或 onStop 中执行重量级的持久化存储操做啦!
看不过瘾?这里只为你 而准备了一份 简洁有力的 《重学安卓》认知地图 😉