旋转屏幕时丢失数据

Rol*_*and 37 android rotation android-activity

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

jai*_*vis 69

//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");  
}
Run Code Online (Sandbox Code Playgroud)

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


Che*_*mon 36

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

  • @RivieraKid我不知道你是否可以依赖它.你见过官方说过的情况吗?我担心一些非品牌手机稍微改变实施,如果它实际上不符合规范.最安全的做法是假设什么都没有保存. (3认同)
  • 虽然一些数据_is_由Android保存 - 例如,`EditText`内容. (2认同)

Roh*_*ngh 11

更多详情

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

屏幕旋转时会发生什么?

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

System 如何创建新实例?

系统尝试使用一组已保存的旧 Activity 实例数据(称为实例状态)重新创建实例。InstanceState 是存储在一个对象中的Key-Value Pair的集合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);
}
Run Code Online (Sandbox Code Playgroud)

因此,如果您错误地忘记调用 super.onSaveInstanceState(savedInstanceState),默认行为将不起作用,即EditText不会保存文本。如果你不相信我看看这个

使用哪种方法来恢复状态?

包括我在内的很多人都感到困惑。我应该选择

  • onCreate(Bundle savedInstanceState)

或者

  • 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);
}
Run Code Online (Sandbox Code Playgroud)

始终调用,super.onRestoreInstanceState(savedInstanceState)以便系统默认恢复视图层次结构


Sur*_*gch 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);
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中,变量Intent在第一次创建活动时从a初始化,但之后它们被初始化savedInstanceState(就像方向改变时).


小智 5

AndroidManifest.xml中添加以下代码

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