web-dev-qa-db-ja.com

画面を回転させるとデータが失われる

私のアプリケーションには少し面白いバグがあります。ユーザーが画面を回転させると、アクティビティのデータの一部が失われます。なぜこれが起こるのかを知っている人はいますか?

35
Roland

デフォルトでは、画面が回転するとアクティビティが強制終了され、再起動されます。データが失われないようにするには、ライフサイクルメソッドを使用してデータを適切に保存および復元する必要があります。 永続状態の保存 を参照してください。

33
Cheryl Simon
//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");  
}

これは、システムが回転時にデータを削除するときにデータを保存する方法です

67
jaisonDavis
8
Theodor Paulus

@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から初期化されます(向きが変わるときなど)。

7
Suragch

AndroidManifest.xmlに次のコードを追加します

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

5
sameer tzar

より詳しく

人々はすでにコードを提供しています。そのため、これについてさらに詳細を追加します。

画面が回転するとどうなりますか?

画面が回転すると、アクティビティの構成が変更されるため、システムはアクティビティにより適したリソースを探します。この目的のために、システムはアクティビティのインスタンスを強制終了し、アクティビティの新しいインスタンスを再作成します。

システムはどのようにして新しいインスタンスを作成しますか?

システムは、instance stateと呼ばれる古いアクティビティインスタンスの保存データのセットを使用して、インスタンスを再作成しようとします。 InstanceStateは、Bundleオブジェクトに格納されたKey-Valueペアのコレクションです。

システムはいくつかのデータを自動的に保存しました

デフォルトでは、システムは、たとえばバンドルにビューオブジェクトを保存します。

  • 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のテキストは保存されません。私を信じないなら チェックアウト

状態を復元するために使用する方法は?

私を含めて多くの人が混乱します。選ぶべきですか

  • onCreate(Bundle savedInstanceState)

OR

  • onRestoreInstanceState(Bundle savedInstanceState)

問題ではありません。両方のメソッドは、パラメーターで同じバンドルを受け取ります。唯一の違いは、onCreate(Bundle savedInstanceState)メソッドでnullチェックを提供する必要があることです。ただし、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)を呼び出します

3
Rohit Singh

AndroidManifest.xmlに次のコードを追加します

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

わたしにはできる

2
Float
setRetainInstance(true);

OnCreateでこれを使用します

2
saurabh yadav

Androidは、画面が回転したときに複雑なオブジェクトを保存できるViewModelを導入しました。 ViewModelクラスは、ライフサイクルを意識した方法でUI関連データを保存および管理するように設計されています。 ViewModelクラスを使用すると、データを画面の回転などの構成変更に耐えることができます。

ドキュメントを参照してください

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

1
Nudge

MVVMパターンを使用し、ViewModelを使用してデータを保存できます。したがって、デバイスをローテーションするときに、ViewModelでデータを分離したため、データが失われる心配はありません。つまり、データはアクティビティライフサイクルの影響を受けません。 https://developer.Android.com/topic/libraries/architecture/viewmodel

0
Ali Mansour