Activityのリビルドとリカバリ
6282 ワード
Activityの再構築については、次の3つの側面から理解できます.
1.システムメモリ不足:androidシステムはプロセスを殺し、システムがメモリを解放する必要がある場合、プロセス内にあるactivityは破棄されます.ユーザーがこのActivityに戻ると、このActivityは再構築されます.
2.Configuration Change(Activity縦画面切り替え、マルチウィンドウモードに入る):縦画面切り替えの場合、システムはレイアウトを調整して新しい構成に適応するため、デフォルトでActivityを再構築します.
3.Activityを呼び出すoncreate()メソッド:トピック切り替え時にoncreateを呼び出してActivityを再構築し、新しいトピックを有効にします.
まず、簡単なコードで、再構築プロセスActivityの状態を見てみましょう.
App実行後に縦横画面を切り替え、上のコード実験で得られた結果は:
I/com.zj.activitylifecycle.LifeCycleActivity: ---> first time onCreate I/com.zj.activitylifecycle.LifeCycleActivity: ---> onStart I/com.zj.activitylifecycle.LifeCycleActivity: ---> onResume I/com.zj.activitylifecycle.LifeCycleActivity: ---> onPause I/com.zj.activitylifecycle.LifeCycleActivity: ---> onSaveInstanceState I/com.zj.activitylifecycle.LifeCycleActivity: ---> onStop I/com.zj.activitylifecycle.LifeCycleActivity: ---> onDestory I/com.zj.activitylifecycle.LifeCycleActivity: ---> recreate I/com.zj.activitylifecycle.LifeCycleActivity: ---> onStart I/com.zj.activitylifecycle.LifeCycleActivity: ---> onRestoreInstanceState I/com.zj.activitylifecycle.LifeCycleActivity:--->onResumeはpaused状態に入るとonSaveInstanceStateを呼び出して必要なデータ状態を保存し、再構築時にonCreateとonRestoreInstanceStateのパラメータで破棄前に保存したデータを取得できます.
いくつかのシーンでは、あなたのActivityは正常に破棄され、ユーザーが戻るキーを押すか、Activity内部でfinish()メソッドを呼び出すと、ユーザーとシステムの観念の中でこのActivityのインスタンスはもう必要ありません.これらのシーンでActivityの破棄は、他の追加作業をする必要はありません.しかし、システムがActivityを破棄するのは、システムの制約(configurationおよびmemory pressure)によるものであり、この場合、ユーザのユーザ体験を維持するためには、ユーザがActivityに戻ったときにActivityの状態を回復する必要がある.この場合、Activityのインスタンスは消えていますが、Activityのインスタンスが存在したことを覚えています.ユーザーがActivityに戻ろうとすると、Activityが破棄されたときに保存した状態とデータを使用して、新しいActivityインスタンスが作成されます.
システムが以前の状態を復元するために保存したデータをinstance stateといい、Bundleに格納されたキー値ペアの集合である.デフォルトでは、Bundleを使用してlayoutのViewの状態(例えばEditTextに入力された情報)を格納し、Activityの再構築時に以前の状態に戻ることを保証します.また、メンバー変数の値やユーザーの進捗情報など、再構築時にリカバリしたい情報を格納することもできます.
ps:ActivityのViewの状態を復元できるように、各Viewには独自のidが必要です(android:idプロパティ定義).
しかし、Bundleは大量のデータを保存するのに適していません.データは保存時にメインスレッドにシーケンス化する必要があり、システムメモリを消費します.比較的多くのデータを保存する必要がある場合は、ローカルストレージと組み合わせることができます.
Viewのステータスシステムは自動的に保存されます.追加する必要はありませんが、他のデータを保存する必要がある場合はonSaveInstanceStateメソッドを書き換えることができます.
データはonCreateまたはonRestoreInstanceStateで復元されます.
onSaveInstanceメソッドは、onPauseの後に呼び出されるたびに呼び出されるわけではありません.Activityが明確なclose(ユーザーが戻るボタンをクリック)またはfinishを呼び出す場合、onSaveInstanceStateは呼び出されません.
preferenceやdatabaseに保存するなど、データを永続化する必要がある場合は、Activityがフロントにいるときに保存するのが最適です.このような機会がなければ、onStopメソッドで保存することができます.
Activityでは、再構築の3つの状況が発生します。
1.システムメモリ不足:androidシステムはプロセスを殺し、システムがメモリを解放する必要がある場合、プロセス内にあるactivityは破棄されます.ユーザーがこのActivityに戻ると、このActivityは再構築されます.
2.Configuration Change(Activity縦画面切り替え、マルチウィンドウモードに入る):縦画面切り替えの場合、システムはレイアウトを調整して新しい構成に適応するため、デフォルトでActivityを再構築します.
3.Activityを呼び出すoncreate()メソッド:トピック切り替え時にoncreateを呼び出してActivityを再構築し、新しいトピックを有効にします.
Activityの再構築時の状態変化:
まず、簡単なコードで、再構築プロセスActivityの状態を見てみましょう.
public class LifeCycleActivity extends AppCompatActivity {
private static final String TAG = LifeCycleActivity.class.getName();
private static final String KEY_TEST = "test";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_life_cycle);
TextView tvContent = findViewById(R.id.tv_content);
if (savedInstanceState == null) {
Log.i(TAG, " ---> first time onCreate");
} else {
Log.i(TAG, " ---> recreate");
String test = savedInstanceState.getString(KEY_TEST);
tvContent.setText(test);
}
findViewById(R.id.btn_start).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
recreate();
}
});
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG, " ---> onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, " ---> onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.i(TAG, " ---> onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.i(TAG, " ---> onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, " ---> onDestory");
}
@Override
protected void onRestart() {
super.onRestart();
Log.i(TAG, " ---> onRestart");
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(KEY_TEST, "testing");
Log.i(TAG," ---> onSaveInstanceState");
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
String test = savedInstanceState.getString(KEY_TEST);
Log.i(TAG, " ---> onRestoreInstanceState");
}
}
App実行後に縦横画面を切り替え、上のコード実験で得られた結果は:
I/com.zj.activitylifecycle.LifeCycleActivity: ---> first time onCreate I/com.zj.activitylifecycle.LifeCycleActivity: ---> onStart I/com.zj.activitylifecycle.LifeCycleActivity: ---> onResume I/com.zj.activitylifecycle.LifeCycleActivity: ---> onPause I/com.zj.activitylifecycle.LifeCycleActivity: ---> onSaveInstanceState I/com.zj.activitylifecycle.LifeCycleActivity: ---> onStop I/com.zj.activitylifecycle.LifeCycleActivity: ---> onDestory I/com.zj.activitylifecycle.LifeCycleActivity: ---> recreate I/com.zj.activitylifecycle.LifeCycleActivity: ---> onStart I/com.zj.activitylifecycle.LifeCycleActivity: ---> onRestoreInstanceState I/com.zj.activitylifecycle.LifeCycleActivity:--->onResumeはpaused状態に入るとonSaveInstanceStateを呼び出して必要なデータ状態を保存し、再構築時にonCreateとonRestoreInstanceStateのパラメータで破棄前に保存したデータを取得できます.
Activityの状態回復
いくつかのシーンでは、あなたのActivityは正常に破棄され、ユーザーが戻るキーを押すか、Activity内部でfinish()メソッドを呼び出すと、ユーザーとシステムの観念の中でこのActivityのインスタンスはもう必要ありません.これらのシーンでActivityの破棄は、他の追加作業をする必要はありません.しかし、システムがActivityを破棄するのは、システムの制約(configurationおよびmemory pressure)によるものであり、この場合、ユーザのユーザ体験を維持するためには、ユーザがActivityに戻ったときにActivityの状態を回復する必要がある.この場合、Activityのインスタンスは消えていますが、Activityのインスタンスが存在したことを覚えています.ユーザーがActivityに戻ろうとすると、Activityが破棄されたときに保存した状態とデータを使用して、新しいActivityインスタンスが作成されます.
システムが以前の状態を復元するために保存したデータをinstance stateといい、Bundleに格納されたキー値ペアの集合である.デフォルトでは、Bundleを使用してlayoutのViewの状態(例えばEditTextに入力された情報)を格納し、Activityの再構築時に以前の状態に戻ることを保証します.また、メンバー変数の値やユーザーの進捗情報など、再構築時にリカバリしたい情報を格納することもできます.
ps:ActivityのViewの状態を復元できるように、各Viewには独自のidが必要です(android:idプロパティ定義).
しかし、Bundleは大量のデータを保存するのに適していません.データは保存時にメインスレッドにシーケンス化する必要があり、システムメモリを消費します.比較的多くのデータを保存する必要がある場合は、ローカルストレージと組み合わせることができます.
Viewのステータスシステムは自動的に保存されます.追加する必要はありませんが、他のデータを保存する必要がある場合はonSaveInstanceStateメソッドを書き換えることができます.
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(KEY_TEST, "testing");
Log.i(TAG," ---> onSaveInstanceState");
}
データはonCreateまたはonRestoreInstanceStateで復元されます.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_life_cycle);
TextView tvContent = findViewById(R.id.tv_content);
if (savedInstanceState == null) {
Log.i(TAG, " ---> first time onCreate");
} else {
Log.i(TAG, "recreate");
String test = savedInstanceState.getString(KEY_TEST);
tvContent.setText(test);
}
findViewById(R.id.btn_start).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
recreate();
// Intent intent = new Intent(LifeCycleActivity.this, SecondActivity.class);
// startActivity(intent);
}
});
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
String test = savedInstanceState.getString(KEY_TEST);
Log.i(TAG, "onRestoreInstanceState");
}
onSaveInstanceメソッドは、onPauseの後に呼び出されるたびに呼び出されるわけではありません.Activityが明確なclose(ユーザーが戻るボタンをクリック)またはfinishを呼び出す場合、onSaveInstanceStateは呼び出されません.
preferenceやdatabaseに保存するなど、データを永続化する必要がある場合は、Activityがフロントにいるときに保存するのが最適です.このような機会がなければ、onStopメソッドで保存することができます.