Activity restart on rotation Android

Activity restart on rotation Android

技术背景

在 Android 开发中,当设备发生旋转(如从竖屏变为横屏)或者键盘可见性改变时,Activity 通常会重新启动,调用 onCreate 方法。这可能会导致一些问题,例如重新加载数据、丢失用户输入等。因此,需要采取一些方法来避免或处理 Activity 的重新启动。

实现步骤

使用 Application 类

创建一个新的类继承 Application,并将初始化代码移到重写的 onCreate 方法中。

Kotlin 版本

1
2
3
4
5
6
class MyApplicationClass: Application {
override fun onCreate() {
super.onCreate()
// Put your application initialization code here
}
}

Java 版本

1
2
3
4
5
6
7
8
public class MyApplicationClass extends Application {

@Override
public void onCreate() {
super.onCreate();
// Put your application initialization code here
}
}

需要在 AndroidManifest.xml 中指定新的 Application 类的名称:

1
2
3
4
<application
android:name="com.you.yourapp.MyApplicationClass"
...
</application>

响应配置更改

AndroidManifest.xml 中为 Activity 添加 android:configChanges 节点,监听会导致重启的事件(如屏幕旋转和键盘可见性改变),并在 Activity 中处理这些事件。

对于 Android 3.2(API 级别 13)及更高版本:

1
2
3
4
5
<activity android:name=".MyActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name">
...
</activity>

然后在 Activity 中重写 onConfigurationChanged 方法:

Kotlin 版本

1
2
3
4
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
setContentView(R.layout.myLayout)
}

Java 版本

1
2
3
4
5
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.myLayout);
}

保存和恢复 Activity 状态

onSaveInstanceState 方法中保存 Activity 的状态,在 onCreateonRestoreInstanceState 方法中恢复状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override
public void onSaveInstanceState(Bundle outState) {
// Save your data to be restored here
// Example: outState.putLong("time_state", time);
super.onSaveInstanceState(outState);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

if (savedInstanceState != null) {
// Restore data when rotation occurs
// Example: time = savedInstanceState.getLong("time_state", 0);
} else {
// When onCreate is called for the first time
}
}

使用 ViewModel

ViewModel 对象在配置更改期间会自动保留,以便它们保存的数据可立即用于下一个 Activity 或 Fragment 实例。

1
2
3
4
5
import androidx.lifecycle.ViewModel

class MyViewModel : ViewModel() {
// ViewModel data and methods
}

限制屏幕旋转

AndroidManifest.xml 中为 Activity 添加 android:screenOrientation 属性,或者在代码中设置屏幕方向。

AndroidManifest.xml 中设置

1
2
3
4
5
6
7
<activity
android:name=".Test"
android:screenOrientation="portrait"
...
>
...
</activity>

在代码中设置

1
2
3
4
5
6
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

核心代码

以下是一个完整的示例,展示了如何使用 android:configChangesonConfigurationChanged 方法来处理屏幕旋转:

AndroidManifest.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import android.content.res.Configuration;
import android.os.Bundle;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);

if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
}

最佳实践

  • 使用 ViewModel:ViewModel 可以在配置更改时保留数据,避免重新加载数据,提高性能。
  • 保存必要的状态:在 onSaveInstanceState 中保存必要的用户输入和状态,以便在 Activity 重新创建时恢复。
  • 使用 android:configChanges 要谨慎:虽然 android:configChanges 可以避免 Activity 重新启动,但可能会导致布局问题。只有在必要时才使用,并且要确保正确处理配置更改。

常见问题

onConfigurationChanged 方法未调用

从 Android 3.2(API 级别 13)开始,屏幕旋转时“屏幕大小”也会改变。因此,如果要防止在 API 级别 13 或更高版本中因方向更改而导致运行时重新启动,必须在 android:configChanges 中包含 screenSize 值。

模拟器和真机表现不一致

在某些情况下,模拟器和真机在处理屏幕旋转时可能会有不同的表现。例如,模拟器可能总是调用 onCreate 方法,而真机可能不会。这可能是由于模拟器的配置或版本问题导致的。可以尝试更新模拟器或在不同的真机上测试。


Activity restart on rotation Android
https://119291.xyz/posts/activity-restart-on-rotation-android/
作者
ww
发布于
2025年7月13日
许可协议