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:禁止切换

参考来源