私はAndroidの初心者です。
Androidでは、一部の一般的な要素を自動的にonSaveInstanceState
/onRestoreInstanceState
に保存/復元できます。
たとえば、EditText
はText
プロパティを保存/復元し、RatingBar
はRating
プロパティを保存/復元します...
いくつかのテストでわかりましたが、ドキュメントではこれについて何も見つかりません。
私の介入なしに、暗黙的に保存/復元されたものをどのように知ることができますか?
たとえば、EditText.Text
は自動的に保存/復元されますか?
特に、すべてのプロパティをテストする必要はありません。
JRG回答から編集:
https://developer.Android.com/guide/components/activities/activity-lifecycle.html
アクティビティを保存しますアクティビティが停止し始めると、システムはonSaveInstanceState()メソッドを呼び出します<...>このメソッドのデフォルトの実装は一時的なEditTextウィジェットのテキストやListViewウィジェットのスクロール位置など、アクティビティのビュー階層の状態に関する情報。
保存/復元のデフォルトの実装を知るにはどうすればよいですか?
JRG回答を再読み込みした後の2番目の編集:
デフォルトでは、システムはBundleインスタンスの状態を使用して、アクティビティレイアウトの各Viewオブジェクトに関する情報を保存します(EditTextウィジェットに入力されたテキスト値など)。
デフォルトの実装では、要素ビューのすべての状態が保存/復元されます。
状態の保存について説明するAndroidドキュメントと、アクティビティとフラグメントでの状態の保存に関する非常に優れた記事。
Android Documentation:
https://developer.Android.com/guide/components/activities/activity-lifecycle.htmlAdditional Article:
https://inthecheesefactory.com/blog/fragment-state-saving-best-practices/enアクティビティ状態の保存と復元ユーザーが[戻る]ボタンを押したときなど、アプリの通常の動作が原因でアクティビティが破棄されるシナリオがいくつかありますアクティビティは、finish()メソッドを呼び出すことにより、自身の破棄を通知します。アクティビティがStopped状態であり、長期間使用されていない場合、またはフォアグラウンドアクティビティがさらにリソースを必要とする場合、システムはアクティビティを含むプロセスを破壊してメモリを回復する場合もあります。
ユーザーが[戻る]を押すか、アクティビティが終了したためにアクティビティが破棄されると、そのアクティビティは不要になったため、システムはそのアクティビティインスタンスの概念を永久に失います。ただし、システムが(通常のアプリの動作ではなく)システムの制約によりアクティビティを破棄した場合、実際のアクティビティインスタンスは失われますが、システムはそれが存在していたことを記憶しているため、ユーザーがそこに戻った場合、システムは新しいアクティビティを作成します。破棄されたときのアクティビティの状態を記述する保存されたデータのセットを使用するアクティビティのインスタンス。システムが以前の状態を復元するために使用する保存されたデータは、インスタンス状態と呼ばれ、Bundleオブジェクトに格納されているキーと値のペアのコレクションです。
デフォルトでは、システムはBundleインスタンス状態を使用して、アクティビティレイアウト内の各Viewオブジェクトに関する情報(EditTextウィジェットに入力されたテキスト値など)を保存します。 したがって、アクティビティインスタンスが破棄されて再作成された場合、レイアウトの状態は、コードを必要とせずに以前の状態に復元されます。ただし、アクティビティには、アクティビティでのユーザーの進行状況を追跡するメンバー変数など、復元したい状態情報がさらに含まれている場合があります。
アクティビティの状態を保存しますアクティビティが停止し始めると、システムがonSaveInstanceState()メソッドを呼び出し、アクティビティがキーのコレクションで状態情報を保存できるようにします-値のペア。このメソッドのデフォルトの実装は、EditTextウィジェットのテキストやListViewウィジェットのスクロール位置など、アクティビティのビュー階層の状態に関する一時的な情報を保存します。アプリは、onPause()メソッドの後、onStop()の前にonSaveInstanceState()コールバックを実装する必要があります。このコールバックをonPause()に実装しないでください。
注意:デフォルトの実装がビュー階層の状態を保存できるように、常にonSaveInstanceState()のスーパークラス実装を呼び出す必要があります。
アクティビティの追加の状態情報を保存するには、onSaveInstanceState()をオーバーライドして、アクティビティが予期せず破棄された場合に保存されるBundleオブジェクトにキーと値のペアを追加する必要があります。例えば:
static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
注:Androidシステムがアクティビティ内のビューの状態を復元するには、各ビューにAndroid:id属性によって提供される一意のIDが必要です。
ユーザー設定やデータベースのデータなどの永続的なデータを保存するには、アクティビティがフォアグラウンドにあるときに適切な機会をとる必要があります。そのような機会が発生しない場合は、onStop()メソッドの実行中にそのようなデータを保存する必要があります。
アクティビティの状態を復元しますアクティビティが以前に破棄された後に再作成された場合、システムがアクティビティに渡すバンドルから保存した状態を復元できます。 onCreate()とonRestoreInstanceState()の両方のコールバックメソッドは、インスタンスの状態情報を含む同じバンドルを受け取ります。
OnCreate()メソッドは、システムがアクティビティの新しいインスタンスを作成している場合でも、以前のインスタンスを再作成している場合でも呼び出されるため、状態バンドルがnullかどうかを確認してから読み取ってください。 nullの場合、システムは、破棄された以前のインスタンスを復元するのではなく、アクティビティの新しいインスタンスを作成します。
たとえば、次のコードスニペットは、onCreate()で状態データを復元する方法を示しています。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
...
}
OnCreate()中に状態を復元する代わりに、システムがonStart()メソッドの後に呼び出すonRestoreInstanceState()の実装を選択できます。システムがonRestoreInstanceState()を呼び出すのは、復元する保存済みの状態がある場合のみなので、バンドルがnullであるかどうかを確認する必要はありません。
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);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}
注意:デフォルトの実装でビュー階層の状態を復元できるように、常にonRestoreInstanceState()のスーパークラス実装を呼び出してください。
これはあなたを説明する例です...
私はシンプルなAndroidプロジェクトを作成しました。このプロジェクトには、アプリのライフサイクルのある時点で何らかの値を持つ合計4つのデータポイントがあります。
saveMe
saveMeNot
withid
(Android:idを持っています)スクリーンショットのとおりの一連のイベントは次のとおりです。
SAVE
ボタンをクリックして、内部変数saveMe
およびsaveMeNot
の値を設定します。 Toast
は、両方の変数の値を保存したことが表示されます。Android:id
でactivity_main.xml
が定義されているすべてのビューの値を保存します。ここでは、Helloのみが保存されます。Helloが入力されたEditTextにはAndroid:id=@+id/withId
が含まれます。テキストHiを含む別のEditTextは、Androidがないため自動的に保存されません。Android:id
がないためです。これは、すべてのビューにAndroid:id
が定義されています。ビューを拡張するカスタムビューがある場合は、Android:id
も定義されています。saveMe
とsaveMeNot
の状態を保存する機能を提供するonSaveInstanceStateとonRestoreInstanceStateも呼び出します。あなたはそれをコード化する必要があるでしょう、そうでなければ状態は失われます。私の例のように、saveMe
ではなくsaveMeNot
の状態を保存しました。これは無料では得られないものです。つまり、コードを記述する必要があります。saveMe
とsaveMeNot
の値を表示するには、CLICK ME
ボタンをクリックしてください。saveMe
の値は、onSaveInstanceState
に保存され、onRestoreInstanceState
で取得されたため、表示されます。ステップのシーケンス
コード
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
package="test.saveinstance">
<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">
<intent-filter>
<action Android:name="Android.intent.action.MAIN" />
<category Android:name="Android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.Java
package test.saveinstance;
import Android.support.v7.app.AppCompatActivity;
import Android.os.Bundle;
import Android.util.Log;
import Android.view.View;
import Android.widget.Button;
import Android.widget.Toast;
public class MainActivity extends AppCompatActivity {
// will save in bundle in onSaveInstanceState
private int saveMe;
// will not save in bundle in onSaveInstanceState
private int saveMeNot;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// do some action that generates values for
// activity specific variables i.e. saveMe
// and saveMeNot
Button saveButton = (Button) findViewById(R.id.save);
saveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
saveMe = 10;
saveMeNot = 20;
Toast.makeText(getApplicationContext(), "SAVED: saveMe: " + saveMe + ";saveMeNot: " + saveMeNot, Toast.LENGTH_LONG).show();
}
});
// will be used to display value of
// saveMe and saveMeNot after orientation
// changes.
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(), "DISPLAY: saveMe: " + saveMe + ";saveMeNot: " + saveMeNot, Toast.LENGTH_LONG).show();
}
});
}
@Override
protected void onSaveInstanceState(Bundle outState) {
// save saveMe in bundle
outState.putInt("saveMe", saveMe);
super.onSaveInstanceState(outState);
Log.d("TEST", "Saving saveMe in bundle during orientation change");
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// retrieve saveMe from bundle
saveMe = savedInstanceState.getInt("saveMe");
Log.d("TEST", "Retrieving saveMe in bundle during orientation change");
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:tools="http://schemas.Android.com/tools"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
tools:context="test.saveinstance.MainActivity">
<EditText
Android:id="@+id/withId"
Android:layout_marginTop="30dp"
Android:layout_width="match_parent"
Android:layout_height="70dp"
Android:gravity="center"
Android:hint="Type Here (has Android:id)" />
<EditText
Android:layout_below="@id/withId"
Android:layout_marginTop="20dp"
Android:layout_width="match_parent"
Android:layout_height="70dp"
Android:gravity="center"
Android:hint="Type Here (doesn't have Android:id)" />
<Button
Android:id="@+id/button"
Android:layout_alignParentBottom="true"
Android:layout_marginBottom="10dp"
Android:text="Click Me"
Android:layout_width="match_parent"
Android:layout_height="50dp" />
<Button
Android:id="@+id/save"
Android:layout_above="@id/button"
Android:layout_marginBottom="10dp"
Android:text="Save"
Android:layout_width="match_parent"
Android:layout_height="50dp" />
</RelativeLayout>