关于 Android 手机横竖屏切换时 Activity 的生命周期问题,网上有很多相似的文章,大多数都是说明在竖屏切换横屏时 Activity 会重启一次,而在横屏切换竖屏时 Activity 会重启两次。
我本身不太理解这样设计的意义,并且觉得新版本会解决这个问题,所以做了一项测试,测试环境为 Android 7.0 模拟器。
测试
测试首先创建一个新的 Activity,并在其各个生命周期方法内打印日志,并执行如下操作得到结果:
在 targetSdkVersion 的值大于 12 时
-
Activity启动
I/System.out: onCreate I/System.out: onStart I/System.out: onResume
-
竖屏切换为横屏
I/System.out: onConfigurationChanged I/System.out: onPause I/System.out: onSaveInstanceState I/System.out: onStop I/System.out: onDestroy I/System.out: onCreate I/System.out: onStart I/System.out: onRestoreInstanceState I/System.out: onResume
-
横屏切回竖屏
I/System.out: onConfigurationChanged I/System.out: onPause I/System.out: onSaveInstanceState I/System.out: onStop I/System.out: onDestroy I/System.out: onCreate I/System.out: onStart I/System.out: onRestoreInstanceState I/System.out: onResume
-
配置
android:configChanges="orientation|screenSize"
后,竖屏切换为横屏I/System.out: onConfigurationChanged
-
配置
android:configChanges="orientation|screenSize"
后,横屏切回竖屏I/System.out: onConfigurationChanged
在 targetSdkVersion 的值小于或等于 12 时
-
Activity启动
I/System.out: onCreate I/System.out: onStart I/System.out: onResume
-
竖屏切换为横屏
I/System.out: onConfigurationChanged I/System.out: onPause I/System.out: onSaveInstanceState I/System.out: onStop I/System.out: onDestroy I/System.out: onCreate I/System.out: onStart I/System.out: onRestoreInstanceState I/System.out: onResume
-
横屏切回竖屏
I/System.out: onConfigurationChanged I/System.out: onPause I/System.out: onSaveInstanceState I/System.out: onStop I/System.out: onDestroy I/System.out: onCreate I/System.out: onStart I/System.out: onRestoreInstanceState I/System.out: onResume
-
配置
android:configChanges="orientation"
后,竖屏切换为横屏I/System.out: onConfigurationChanged
-
配置
android:configChanges="orientation"
后,横屏切回竖屏I/System.out: onConfigurationChanged
总结
可以发现新版本 Android 设备上的运行结果和网上的结论并不完全相同,在横竖屏切换时,都会调用一次 onConfigurationChanged,并重启 Activity 一次,行为完全一致,具体的生命周期为:
I/System.out: onConfigurationChanged
I/System.out: onPause
I/System.out: onSaveInstanceState
I/System.out: onStop
I/System.out: onDestroy
I/System.out: onCreate
I/System.out: onStart
I/System.out: onRestoreInstanceState
I/System.out: onResume
在 targetSdkVersion 的值大于 12 时,配置 android:configChanges="orientation|screenSize"
,
在 targetSdkVersion 的值小于或等于 12 时,配置 android:configChanges="orientation"
,
可以做到拦截 Activity 的重新创建:
I/System.out: onConfigurationChanged
后续
将会对过去版本的 Android 设备做相应的测试,来验证得到结果。
改进
通常研究设备旋转带来的 Activity 重启问题,是为了解决 Activity 重启导致成员变量未保存引发运行出错。但之所以 Activity 会重启是因为运行时配置发生了更变,可能有更适合的资源来匹配新的设备配置,例如在横屏时,有更好利用空间的横版布局资源,这时就需要 Activity 重新加载布局显示。
所以,好的解决办法是利用 onSaveInstanceState(Bundle outState)
方法保存成员变量的值到 Bundle 对象中,在 Activity 重启后,再在 onCreate(Bundle savedInstanceState)
中获取这些保存的信息。