近日有消息称:招商银行上海川北支行6月26日向上海市高级人民法院申请财产保全,请求冻结乐视相关公司及贾跃亭夫妇资产共计12.3亿元,或查封、扣押其他等值财产。对此乐视相关负责人表示:“招行申请的资产冻结,起因是一笔乐视手机业务融资贷款。但我们针对此笔贷款的资产抵押,足够覆盖债务。公司高层也正在与招商银行在内的各金融机构紧密沟通中,希望尽快解决相关债务问题。”
本篇是
马伟奇
的投稿,分享了 onSaveInstanceState源码内核分析,希望能够帮助到大家。
马伟奇
的博客地址:
http://www.jianshu.com/u/53e5012c55a3
经常有人问,后台的 activity 被系统自动回收的话,怎么回到界面的时候恢复数据,通过一个真实案例给大家讲讲如何保存状态,然后带着大家分析 onSaveInstanceState 的源码。
当前页面侧滑菜单指向专题,用户做了如下操作:
失去焦点,activity 很可能被进程终止!被 KILL 掉了,这时候就需要能保存当前的状态,不然下次用户再次进来看到的还是新闻,这样用户体验就不够好,代码有删减,我自己项目就这样使用的,解决方案如下:
如上代码可知:
界面被回收之后调用 onSaveInstanceState 方法保存当前的状态,每个侧滑菜单选项都有一个位置。
由以上代码可知:
判断当前 Bundle 是否有刚刚我们保存的位置,如果不为空,从当前的 Bundle 取出来,给每一个位置赋值。
以上代码可知:
根据当前的位置设置到 adapter 当中,这样下次用户进来就还是专题了。
总结下 savedInstanceState 的使用,代码如下:
横竖屏切换,打印结果如下:
从打印结果可以看出来,当前 Activity 被系统回收之后,会调用 onSaveInstanceState() 保存状态,然后在 activity 判断 bundler 是否有当前状态,如果只是到这,估计你们就会吐槽没啥含金量,没办法硬着头皮上,接着咱们来分 onSaveInstanceState() 源码,请看如下代码:
以上代码可知
调用父类 Activity 源码里面的 onSaveInstanceState 方法,代码如下:
以上代码可知
以上代码可知
-
Bundle outState = new Bundle() 初始化 Bundle 对象,Bundle 实现了 Parcelable 接口。
-
states = new SparseArray
() 并且把自己放到 outState 当中。
-
mContentParent.saveHierarchyState(states),整个 View 树的顶层视图保存了层级状态代码如下:
以上代码可知:
调相应的 dispatchSaveInstanceState 方法,代码如下:
以上代码可知:
经常当我们看不懂谷歌源码的时候,可以通过曲线救国的方式,看看英文注释,看看源码哪个地方用到当前的类或者方法或者变量,这样就好理解了,好了扯远了,继续分析代码;
-
通过if判断,检测子类是否调用父类的 onSaveInstanceState() 方法,否则会抛异常,突然看到这才明白,还记得刚刚开始学 Android 的时候,经常一不小心就把代码里面的 super.onCreate(savedInstanceState); 这行代码删掉,报了错误还看不懂,原来系统在这里检测了,都怪自己曾经太年轻。
-
container.put(mID, state) 这行代码,将 state 放进 SparseArray 中,以 view 自身的 id为 key,并且从注释来看打印 mID 的 Hex 值用来保证每页的 id 必须是唯一的,难怪每当我给 view 取 id 的时候,一个页面有重复的 id 就会报错,谷歌大婶在这里做判断了,腻害了 word 哥,总是百思不得其姐,凭啥不让我共用 id (因为取名字太难了),原来是想把 id 做为 key 来使用。
-
走到这 onSaveInstanceState(),调用如下代码:
以上代码可知: