专栏名称: 郭霖
Android技术分享平台,每天都有优质技术文章推送。你还可以向公众号投稿,将自己总结的技术心得分享给大家。
目录
相关文章推荐
开发者全社区  ·  广州员工奴性事件 ·  9 小时前  
开发者全社区  ·  大S走了,两任老公争遗产式撕逼表演 ·  20 小时前  
开发者全社区  ·  恒大歌舞团团长嫁人了 ·  23 小时前  
鸿洋  ·  ActivityTaskManagerSer ... ·  昨天  
鸿洋  ·  关于 2025 副业探索,DeepSeek ... ·  2 天前  
51好读  ›  专栏  ›  郭霖

Activity被回收怎么办?带你解析onSaveInstanceState的源码

郭霖  · 公众号  · android  · 2017-07-04 08:03

正文

今日科技快讯

近日有消息称:招商银行上海川北支行6月26日向上海市高级人民法院申请财产保全,请求冻结乐视相关公司及贾跃亭夫妇资产共计12.3亿元,或查封、扣押其他等值财产。对此乐视相关负责人表示:“招行申请的资产冻结,起因是一笔乐视手机业务融资贷款。但我们针对此笔贷款的资产抵押,足够覆盖债务。公司高层也正在与招商银行在内的各金融机构紧密沟通中,希望尽快解决相关债务问题。”

作者简介

本篇是 马伟奇 的投稿,分享了 onSaveInstanceState源码内核分析,希望能够帮助到大家。

马伟奇 的博客地址:

http://www.jianshu.com/u/53e5012c55a3

正文

经常有人问,后台的 activity 被系统自动回收的话,怎么回到界面的时候恢复数据,通过一个真实案例给大家讲讲如何保存状态,然后带着大家分析 onSaveInstanceState 的源码。

当前页面侧滑菜单指向专题,用户做了如下操作:

  • 当用户按下 HOME 键时。

  • 长按 HOME 键,选择运行其他的程序时。

  • 按下电源按键(关闭屏幕显示)时。

  • 从activity A中启动一个新的 activity 时。

  • 屏幕方向切换时,例如从竖屏切换到横屏时。

失去焦点,activity 很可能被进程终止!被 KILL 掉了,这时候就需要能保存当前的状态,不然下次用户再次进来看到的还是新闻,这样用户体验就不够好,代码有删减,我自己项目就这样使用的,解决方案如下:

如上代码可知:

界面被回收之后调用 onSaveInstanceState 方法保存当前的状态,每个侧滑菜单选项都有一个位置。

由以上代码可知:

判断当前 Bundle 是否有刚刚我们保存的位置,如果不为空,从当前的 Bundle 取出来,给每一个位置赋值。

以上代码可知:

根据当前的位置设置到 adapter 当中,这样下次用户进来就还是专题了。

总结下 savedInstanceState 的使用,代码如下:

横竖屏切换,打印结果如下:

从打印结果可以看出来,当前 Activity 被系统回收之后,会调用 onSaveInstanceState() 保存状态,然后在 activity 判断 bundler 是否有当前状态,如果只是到这,估计你们就会吐槽没啥含金量,没办法硬着头皮上,接着咱们来分 onSaveInstanceState() 源码,请看如下代码:

以上代码可知

调用父类 Activity 源码里面的 onSaveInstanceState 方法,代码如下:

以上代码可知

  • outState.put 一个 tag 调用了 mWindow 里面的 saveHierarchyState 方法,继续分析Window源代码。

  • window 是抽象类调用子类 PhoneWindow 里面的 saveHierarchyState 方法代码如下:

以上代码可知

  • Bundle outState = new Bundle() 初始化 Bundle 对象,Bundle 实现了 Parcelable 接口。

  • states = new SparseArray () 并且把自己放到 outState 当中。

  • mContentParent.saveHierarchyState(states),整个 View 树的顶层视图保存了层级状态代码如下:

以上代码可知:

调相应的 dispatchSaveInstanceState 方法,代码如下:

以上代码可知:

  • 原来 NO_ID 用来标记没有 id 的 View,搜索 mID 可知原来在如下代码赋值

经常当我们看不懂谷歌源码的时候,可以通过曲线救国的方式,看看英文注释,看看源码哪个地方用到当前的类或者方法或者变量,这样就好理解了,好了扯远了,继续分析代码;

  • 通过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(),调用如下代码:

以上代码可知:







请到「今天看啥」查看全文