03-Activity横竖屏切换与configChanges
Activity 横竖屏切换与 configChanges
1. 横竖屏切换为什么会影响生命周期?
横竖屏切换属于系统配置变化。
例如:
竖屏 → 横屏
横屏 → 竖屏
屏幕方向变化后,屏幕尺寸、布局资源、图片资源等都可能发生变化,所以 Android 默认可能会销毁并重建 Activity,以便重新加载适合当前配置的资源。
2. 默认情况下的生命周期
如果不做特殊配置,横竖屏切换时通常会发生 Activity 重建。
可以理解为:
onPause()
onSaveInstanceState()
onStop()
onDestroy()
onCreate()
onStart()
onRestoreInstanceState()
onResume()
注意:onSaveInstanceState() 和 onStop() 的顺序存在版本差异。
| 版本 / target 情况 | 顺序说明 |
|---|---|
| API 28 之前 | onSaveInstanceState() 一般在 onStop() 前 |
| target API 28+ | onSaveInstanceState() 在 onStop() 后 |
所以实际开发中不要强依赖它们的精确顺序。
3. 保存和恢复横竖屏切换前的状态
保存:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("content", editText.getText().toString());
}
恢复:
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
String content = savedInstanceState.getString("content");
editText.setText(content);
}
也可以在 onCreate() 中恢复:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
String content = savedInstanceState.getString("content");
}
}
4. android:configChanges 的作用
android:configChanges 用来告诉系统:
这些配置变化我自己处理,不要销毁并重建 Activity。
示例:
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize" />
配置后,横竖屏切换时 Activity 通常不会重走:
onPause()
onStop()
onDestroy()
onCreate()
而是回调:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
// 横屏处理
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
// 竖屏处理
}
}
所以不能说“什么也没有调用”,正确说法是:
生命周期不会重建,但会调用 onConfigurationChanged()
5. 版本差异:为什么 orientation 往往不够?
早期笔记经常写:
android:configChanges="orientation"
但在较新的 Android 版本中,横竖屏切换往往不仅改变方向,还会改变屏幕尺寸。
因此 target API 13+ 后,通常要写:
android:configChanges="orientation|screenSize"
在大屏、折叠屏、多窗口场景下,尺寸、布局状态变化更复杂,必要时还要考虑:
android:configChanges="orientation|screenSize|screenLayout"
但这不代表所有项目都应该这样写。
6. 什么时候应该自己处理配置变化?
适合使用 configChanges 的场景:
视频播放页面
相机页面
游戏页面
地图页面
复杂渲染页面
横竖屏切换时不想中断任务的页面
不建议滥用的场景:
普通表单页面
普通列表页面
普通详情页面
普通设置页面
因为默认重建虽然麻烦,但能自动使用新的资源:
layout-land
drawable-land
values-land
如果你选择自己处理配置变化,就要自己保证横屏、竖屏、大屏、折叠屏、多窗口下 UI 都正确。
7. 固定竖屏或横屏
如果页面根本不希望旋转,可以固定方向。
固定竖屏:
<activity
android:name=".MainActivity"
android:screenOrientation="portrait" />
固定横屏:
<activity
android:name=".MainActivity"
android:screenOrientation="landscape" />
代码设置:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
或:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
8. 大屏、折叠屏、多窗口下的注意点
现代 Android 设备不再只有手机竖屏和横屏。
还要考虑:
平板
折叠屏
分屏
自由窗口
ChromeOS
外接显示器
这些场景中,Activity 尺寸可能变化,但不一定是传统横竖屏切换。
所以更推荐的思路是:
普通页面:让系统重建,使用响应式布局恢复状态
特殊页面:使用 configChanges 自己处理,避免中断播放、拍摄、渲染等任务
9. 总结
默认横竖屏切换:Activity 销毁重建
使用 configChanges:Activity 不重建,回调 onConfigurationChanged()
固定 screenOrientation:禁止方向切换
记忆口诀:
不配置:系统重建
配 configChanges:自己处理
配 screenOrientation:禁止切换
参考来源
- 原始 PDF:《01、Activity知识总结.pdf》
- Android 官方文档:Activity 生命周期
https://developer.android.com/guide/components/activities/activity-lifecycle - Android 官方文档:Activity API Reference
https://developer.android.com/reference/android/app/Activity - Android 官方文档:处理配置变更
https://developer.android.com/guide/topics/resources/runtime-changes - Android 官方文档:
<activity>manifest 配置
https://developer.android.com/guide/topics/manifest/activity-element - Android 官方文档:Tasks and back stack
https://developer.android.com/guide/components/activities/tasks-and-back-stack - Android 官方文档:Services overview
https://developer.android.com/develop/background-work/services
03-Activity横竖屏切换与configChanges
https://lautung.com/archives/03-activity%E6%A8%AA%E7%AB%96%E5%B1%8F%E5%88%87%E6%8D%A2%E4%B8%8Econfigchanges