概述
在android 的activity 内部实例保存有很多方式,比较官方的有onSaveInstanceState ,Fragment的setRetainInstance或者是Jetpack的ViewModel。
onRetainNonConfigurationInstance
但今天我要讲的是onRetainNonConfigurationInstance ,首先这个是在android.os.Build.VERSION_CODES#HONEYCOMB(API 11)版本 或者更高版本已经弃用了,但不代表他没有作用,Fragment的setRetainInstance或者是Jetpack的ViewMode的内部实现都会依赖此方法作为保存实例的基石。
只是不建议用户使用,可以使用兼容包或者androidx时的onRetainCustomNonConfigurationInstance方法,因为在兼容包或者androidx中会在onRetainNonConfigurationInstance 重新实现 和retainNonConfigurationInstances内部相似的状态保存,如果用用户在重写onRetainNonConfigurationInstance会覆盖此逻辑导致兼容包或者androidx的相关逻辑会一定的影响。
如果是用原生Activity开发则不用考虑此问题,例如一些做ROM系统应用,不需要兼容版本,只需针对当前版本开发, 当然如果一定要用兼容包的Activity则也要遵守以上规则。
好了,言归正传,刚才所说的基石,我是这么形容onRetainNonConfigurationInstance的,那么我们来看看他的运行机制,先上一张图
这个整体流程上还是比较单一的,只有重启activity的时候才会触发此保存的逻辑,并且和
对比onSaveInstanceState
onSaveInstanceState对比,不同之处有如下几点:
1 保存对象限制
onSaveInstanceState只能保存Bundle对象,而onRetainNonConfigurationInstance则是Object。
2 保存的生命周期长短,onSaveInstanceState可以保存到AMS内部,就算被系统意外杀死,待下次重启Activity的时候恢复状态数据;而onRetainNonConfigurationInstance只是本地应用保存,如果被系统杀死则无法保存数据。
onSaveInstanceState为什么能保存?
首先是应用会在stop Activity 的时候把state数据保存在AMS 的 ActivityRecord的icicle变量中, 就算系统杀死应用 ,也不会影响AMS的内部ActivityRecord存储
可以通过dumpsys activity activities 命令查看AMS 的activity 堆栈信息, 在杀死应用前后 ActivityRecord 的对象地址一直未变化;再次启动应用 会复用ActivityRecord信息。