问题描述
我有一个奇怪的问题,发生在Android 10上,当我开始新的景观活动时,下面的活动将重新创建。
假设有两个Activity
类:
ActivityA: orientation = unspecified
ActivityB: orientation = force landscape,full screen,opaque
如果我从ActivityB
开始ActivityA
,则生命周期事件的日志:
D/ActivityA: onPause() called
D/ActivityB: onCreate() called
D/ActivityB: onStart() called
D/ActivityB: onResume() called
D/ActivityA: onStop() called
D/ActivityA: onDestroy() called
D/ActivityA: onCreate() called
D/ActivityA: onStart() called
D/ActivityA: onResume() called
D/ActivityA: onPause() called
D/ActivityA: onStop() called
可以清楚地看到ActivityA
被重新创建,而且在ActivityA#onResume
之后又以某种方式调用了ActiviyB#onResume
?
好的,现在我们在堆栈顶部有ActivityB
,然后按返回按钮:
D/ActivityB: onPause() called
D/ActivityA: onStart() called
D/ActivityA: onResume() called
D/ActivityA: onPause() called
D/ActivityA: onStop() called
D/ActivityA: onDestroy() called
D/ActivityA: onCreate() called
D/ActivityA: onStart() called
D/ActivityA: onResume() called
D/ActivityB: onStop() called
D/ActivityB: onDestroy() called
ActivityA
是否重新创建?
正如我在设备中看到的那样,有一个动画,ActivityA
在ActivityB
可见之前旋转为横向模式,并且当ActivityB
退出时,ActivityA
再次旋转为纵向模式。此行为可能导致ActivityA
一次又一次地重新创建。
这很麻烦,您是否知道如何防止在这种情况下重新创建ActivityA
,或者这是Android本身的错误?
更新1
我可以轻松处理ActivityA
上的配置更改,问题是ActivityA
具有非常复杂的视图结构,不必要地重新创建它会导致UI滞后,而且活动的生命周期回调混乱也将导致逻辑中断。
更新2
我刚刚发现recreate()
类两次调用了AppCompatDelegateImpl
方法,这就是为什么我会得到奇怪的生命周期行为的原因:
解决方法
您可能对此行为无能为力。如果不会给您带来太多问题,我建议您采取以下措施:
- 将
android:configChanges="orientation"
添加到ActivityA
的清单条目中 - 在
onConfigurationChanged()
中实施ActivityA
并自行处理方向改变
这将防止Android在更改方向时杀死并重新创建ActivityA
。
不仅您遇到了这个问题(很多人都这样),这是一个待修复的错误,实际上不应该被弄乱,我可以知道您所使用的设备吗?在评论中您可能会说。
,在景观/肖像上重新创建活动是Android设计的功能(不是bug),因为通过编程方式,只需重新绘制UI而不是找出元素的重新放置/调整大小,它就更容易。即使在没有B的情况下,只要在A上翻转方向,您也应该获得相同的效果。Android文档(https://developer.android.com/guide/components/activities/state-changes#cco)中也对此进行了很好的描述
这应该不是太大的问题,只要您不保留对活动本身的任何引用即可;此时的资源已经被缓存,因此几乎没有Flash I / O,大部分工作将是重新创建视图。
,默认情况下,每次轮换后都会重新创建活动,如官方活动生命周期onDestroy()文档所述。
如果您希望活动的UI状态在整个配置更改(例如轮换)中保持不变,则应使用ViewModel,onSaveInstanceState()和/或本地存储的组合来保留用户的瞬时UI状态,如下面所述。 Saving and restoring transient UI state
您可以使用AndroidManifest中活动标签的config changes属性覆盖此行为。有关更多详细信息和其他选项,请参见Handle configuration changes
最后,您可以在此处了解有关Activity Lifecycle in Context of Screen Rotation的更多信息。
,这看起来像是特定于设备的错误。
我尝试了您在Pixel 3a(API 29&30)模拟器上的代码。这就是我得到的:
从ActivityB
开始ActivityA
时:
D/MainActivityA: onPause() called
D/MainActivityB: onCreate() called
D/MainActivityB: onStart() called
D/MainActivityB: onResume() called
D/MainActivityA: onStop() called
在后退按钮上按下:
D/MainActivityB: onPause() called
D/MainActivityA: onStart() called
D/MainActivityA: onResume() called
D/MainActivityB: onStop() called
D/MainActivityB: onDestroy() called
您应该file an issue使用适当的Android版本和使用的设备
问题中关于更新2的想法:
日志显示onConfigurationChanged(Configuration)
正在被调用。 Documentation指出,将在运行时配置更改时重新创建活动。
您可以做的是在“活动”中覆盖onConfigurationChanged(Configuration)
并记录配置对象以查看更改了哪些设备配置。可能是Orientation
,Screen size
,ScreenLayout
或Keyboard availability