旋转屏幕时丢失数据

时间:2011-02-25 22:29:11

标签: android android-activity rotation

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

12 个答案:

答案 0 :(得分:66)

//Use onSaveInstanceState(Bundle) and onRestoreInstanceState

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {

  // Save UI state changes to the savedInstanceState.   
  // This bundle will be passed to onCreate if the process is  
  // killed and restarted.

  savedInstanceState.putBoolean("MyBoolean", true);  
  savedInstanceState.putDouble("myDouble", 1.9);  
  savedInstanceState.putInt("MyInt", 1);  
  savedInstanceState.putString("MyString", "Welcome back to Android");  

  // etc.  

  super.onSaveInstanceState(savedInstanceState);  
}  

//onRestoreInstanceState  

@Override  
public void onRestoreInstanceState(Bundle savedInstanceState) {  

  super.onRestoreInstanceState(savedInstanceState);  

  // Restore UI state from the savedInstanceState.  
  // This bundle has also been passed to onCreate.  

  boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");  
  double myDouble = savedInstanceState.getDouble("myDouble");  
  int myInt = savedInstanceState.getInt("MyInt");  
  String myString = savedInstanceState.getString("MyString");  
}

这是系统在轮换时删除数据时的保存方式。

答案 1 :(得分:32)

默认情况下,当屏幕旋转时,您的Activity将被终止并重新启动。要确保没有数据丢失,您需要使用生命周期方法正确保存和恢复数据。请参阅Saving Persistent State

答案 2 :(得分:8)

答案 3 :(得分:7)

这是@ 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);
}

在此示例中,变量在第一次创建活动时从Intent初始化,但之后会从savedInstanceState初始化(就像方向更改时一样)。

答案 4 :(得分:4)

AndroidManifest.xml 中添加以下代码

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

答案 5 :(得分:3)

更多详情

人们已经提供了代码。所以我将添加更多细节。

屏幕旋转时会发生什么?

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

System如何创建新实例?

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

系统自动保存了一些数据

默认情况下,系统将View对象保存在Bundle中。例如。

  • EditText中的文字
  • 在ListView等中滚动位置

如果您想存储更多数据,这些数据应该可以在更改方向时使用。您应该覆盖onSaveInstanceState(Bundle savedInstanceState)方法。

正确使用onSaveInstaneState

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}
  

如果忘记打电话,那就错了   super.onSaveInstanceState(savedInstanceState)的默认行为   将无效,即EditText中的文字将无法保存。   如果你不相信我check this out

使用哪种方法恢复状态?

很多人都对我感到困惑。我应该选择

  • onCreate(Bundle savedInstanceState)

OR

  • onRestoreInstanceState(Bundle savedInstanceState)

没关系。两种方法都在参数中接收相同的包。唯一的区别是您需要在onCreate(Bundle savedInstanceState)方法中提供空检查。但是,如果您打算使用onRestoreInstanceState(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)   系统默认恢复View层次结构

答案 6 :(得分:2)

setRetainInstance(true);

在OnCreate

上使用此功能

答案 7 :(得分:1)

Android引入了ViewModel,它可以在旋转屏幕时存储复杂对象。 ViewModel类旨在以生命周期感知的方式存储和管理与UI相关的数据。 ViewModel类允许数据在配置更改(例如屏幕旋转)中幸免。

请参阅文档

https://developer.android.com/topic/libraries/architecture/viewmodel

答案 8 :(得分:1)

在AndroidManifest.xml中添加以下代码

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

对我有用

答案 9 :(得分:0)

您可以使用MVVM模式并使用ViewModel来保存数据。因此,当您旋转设备时,您不必担心丢失数据,因为您在ViewModel中隔离了数据,这意味着数据不会受到活动生命周期的影响。 https://developer.android.com/topic/libraries/architecture/viewmodel

答案 10 :(得分:0)

configChanges 解决了我的问题

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

答案 11 :(得分:0)

“ViewModel”是一个设计用于在配置更改(例如屏幕旋转)中幸存下来的类,并且可以保留视图所需的信息。当“View”(即片段/活动)通过改变设备的配置或旋转而被销毁时,它的“ViewModel”不会被销毁,并且一个新的View实例将重新连接到同一个“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
    }
}