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() } }
Java 版本 1 2 3 4 5 6 7 8 public class MyApplicationClass extends Application { @Override public void onCreate () { super .onCreate(); } }
需要在 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 的状态,在 onCreate
或 onRestoreInstanceState
方法中恢复状态。
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) { super .onSaveInstanceState(outState); }@Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState != null ) { } else { } }
使用 ViewModel ViewModel 对象在配置更改期间会自动保留,以便它们保存的数据可立即用于下一个 Activity 或 Fragment 实例。
1 2 3 4 5 import androidx.lifecycle.ViewModelclass MyViewModel : ViewModel () { }
限制屏幕旋转 在 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:configChanges
和 onConfigurationChanged
方法来处理屏幕旋转:
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
方法,而真机可能不会。这可能是由于模拟器的配置或版本问题导致的。可以尝试更新模拟器或在不同的真机上测试。