Android 旋转屏幕时丢失数据

Android 旋转屏幕时丢失数据,android,android-activity,rotation,Android,Android Activity,Rotation,我的应用程序中有一个有趣的错误。当用户旋转屏幕时,我会丢失活动中的一些数据。有人知道为什么会这样吗 默认情况下,当屏幕旋转时,您的活动被终止并重新启动。为了确保没有数据丢失,您需要使用生命周期方法正确保存和恢复数据。看 这是系统在循环删除数据时保存数据的方式。我找到的最快解决方案是: 以下是@jaisonDavis有用答案的变体: int myInt; String myString; protected void onCreate(Bundle savedInstanceState) {

我的应用程序中有一个有趣的错误。当用户旋转屏幕时,我会丢失活动中的一些数据。有人知道为什么会这样吗

默认情况下,当屏幕旋转时,您的活动被终止并重新启动。为了确保没有数据丢失,您需要使用生命周期方法正确保存和恢复数据。看


这是系统在循环删除数据时保存数据的方式。我找到的最快解决方案是:
以下是@jaisonDavis有用答案的变体:

int myInt;
String myString;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_verses);


    if (savedInstanceState == null) {

        Intent intent = getIntent();
        myInt = intent.getIntExtra("MyIntIntentKey", DEFAULT_INT);
        myString = intent.getStringExtra("MyStringIntentKey", DEFAULT_STRING);

    } else { // savedInstanceState has saved values

        myInt = savedInstanceState.getInt("MyIntKey");
        myString = savedInstanceState.getString("MyStringKey");
    }

}

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {

    savedInstanceState.putInt("MyIntKey", myInt);
    savedInstanceState.putString("MyStringKey", myString);

    super.onSaveInstanceState(savedInstanceState);
}

在本例中,变量在第一次创建活动时从
意图
初始化,但之后从
savedInstanceState
初始化(如方向改变时)。

这将解决保留状态的问题,但它只适用于
片段
,而不是标准的
活动

setRetainInstance(true);

onCreate()
方法中调用此函数

在AndroidManifest.xml中添加以下代码

<activity android:name=".MainActivity"
            android:configChanges="keyboardHidden|orientation|screenSize"
            >

更多详细信息 人们已经提供了代码。所以我要补充更多的细节

当屏幕旋转时会发生什么? 当屏幕旋转时,活动的配置会发生变化,因此系统会为活动寻找更合适的资源。为此,系统将终止活动实例并重新创建新的活动实例

系统如何创建新实例? 系统尝试使用一组保存的旧活动实例数据(称为实例状态)重新创建实例。InstanceState是存储在
对象中的键值对的集合

系统自动保存了一些数据 例如,默认情况下,系统将视图对象保存在捆绑包中

  • 编辑文本中的文本
  • 滚动列表视图中的位置等
如果您想存储更多的数据,这些数据应该能够经受住方向的变化。您应该重写saveInstanceState(Bundle savedInstanceState)方法

正确使用OnSaveInstanceEstate 所以如果你忘了打电话 super.onSaveInstanceState(savedInstanceState)默认行为 将不起作用。
EditText
中的文本将不保存。 如果你不相信我

使用哪种方法恢复状态? 包括我在内的许多人都感到困惑。我应该选择吗

  • onCreate(Bundle savedInstanceState)

  • onRestoreInstanceState(Bundle savedInstanceState)
没关系。两个方法在参数中接收相同的包。唯一的区别是您需要在
onCreate(Bundle savedInstanceState)
方法中提供一个空检查。但是如果要在RestoreInstanceState(Bundle savedInstanceState)上使用
请小心使用它

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);

    // Restore state members from saved instance
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
}
始终调用super.onRestoreInstanceState(savedInstanceState)
,以便 系统默认情况下还原视图层次结构


Android引入了
ViewModel
,当屏幕旋转时,它可以存储复杂的对象。
ViewModel
类旨在以生命周期意识的方式存储和管理与UI相关的数据。
ViewModel
类允许数据在配置更改(如屏幕旋转)后仍然有效

请参阅文件


在AndroidManifest.xml中添加以下代码

<activity android:name=".MainActivity"
            android:configChanges="keyboardHidden|orientation|screenSize"
            >


它适用于我

您可以使用MVVM模式并使用ViewModel保存数据。因此,当您旋转设备时,您不会担心丢失数据,因为您在ViewModel中隔离了数据,这意味着您的数据不会受到活动生命周期的影响。
配置更改解决了我的问题

<activity android:name=".MyActivity"
      android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
      android:label="@string/app_name">

一个“ViewModel”是一个设计用于保存配置更改(如屏幕旋转)的类,可以保存视图所需的信息。当通过更改设备的配置或旋转来销毁“视图”(即片段/活动)时,其“ViewModel”不会被销毁,新的视图实例将重新连接到同一个“ViewModel”

这就是ViewModel中的代码可能的样子,以便View可以保存数据:

private boolean mSomeBooleanData = false;

public boolean getSomeBooleanData(){
    return mSomeBooleanData;
}

public void setSomeBooleanData (boolean data) {
    mSomeBooleanData = data;
}
现在,在Activity/Fragment类中的某个地方,从ViewModel调用这些方法,我们可以使用以下方法保存旋转期间要保存的数据:

mViewModel.setSomeBooleanData(true);
然后,在onResume()方法中重新创建Activity/Fragment类时,我们可以从ViewModel中查找保存的数据,并对其进行处理:

public void onResume(){
    super.onResume();
   
    if (mViewModel.getSomeBooleanData()){
        //...Do something when saved data is True
    } else {
        //...Do something when saved data is False
    }
}

虽然有些数据是由Android-
EditText
contents保存的,例如。@RivieraKid我不知道你是否可以依赖它。你有没有看到任何地方的官员说这是事实?我会担心一些非品牌手机会稍微改变实现,如果它实际上不在规范中的话。最安全的做法是假设没有保存任何内容。@CherylSimon有
freezesText
属性,默认情况下
EditText
设置为
true
。官方文件是。我从这里得到的。注意!super.onSaveInstanceState(savedInstanceState)应该在放置值之前调用。onRestoreInstanceState并不总是被调用。有趣的答案是:可以强制方向,使其无法旋转。如果持久性比允许旋转更重要,那么它是首选。在这种情况下,它保留了包括布局在内的所有内容。我希望布局应随方向而改变,但对象(如TextView)应继续显示旋转前显示的值。尽管这可能满足某些需要,但应避免使用此解决方案,除非它是最后的选择。在Android文档的开头甚至有一个警告。你从哪里得到这个方法的
public void onResume(){
    super.onResume();
   
    if (mViewModel.getSomeBooleanData()){
        //...Do something when saved data is True
    } else {
        //...Do something when saved data is False
    }
}