ユーザーがアプリの内外を移動してからアプリに戻ると、アプリ内の Activity
インスタンスはライフサイクルのさまざまな状態の間を遷移します。
Activity
クラスには、いくつかのコールバックが用意されています。
状態が変化したときや、アクティビティの状態が
アクティビティの作成、停止、再開、または破棄をシステムが
アクティビティが存在するプロセスを
定義しなくてはなりません
ライフサイクル コールバック メソッド内で、ユーザーがアクティビティを離れてから戻った場合のアクティビティの動作を宣言できます。たとえば 作成する場合は、動画を一時停止して ネットワーク接続を維持できます。ユーザーが戻ってくると ネットワークに接続してユーザーが 同じ位置にあります
各コールバックにより、特定の処理を 適切に調整できる必要があります。適切な作業を適切なタイミングで行い、移行を正しく処理することで、アプリの堅牢性とパフォーマンスが向上します。 たとえば、ライフサイクル コールバックを適切に実装すると、アプリの 次のようなことは避けてください。
- アプリの使用中にユーザーが電話を受信したり、別のアプリに切り替えたりするとクラッシュする。
- ユーザーが実際に使用していない場合に、貴重なシステム リソースが消費される。
- ユーザーがアプリを離れてから後で戻ると、ユーザーの進捗状況が失われる。
- 画面が横向きと縦向きの表示を切り替えている間に、クラッシュする、またはユーザーの進捗状況が失われる。
このドキュメントでは、アクティビティのライフサイクルについて詳しく説明します。最初にライフサイクル パラダイムについて説明します。次に、各コールバックについて説明します。 実施中に内部で何が行われるのか そして何を実装する必要があるのか あります。
続いて、アクティビティの状態とシステムの強制終了に対するプロセスの脆弱性との関係を簡単に紹介します。 最後に、クラウド コンピューティング モデル間の移行に関連する 表示することもできます。
ライフサイクルの処理に関する情報(以下を含む)は、 ベスト プラクティスについては、 ライフサイクル対応コンポーネントによるライフサイクルへの対応と UI の状態を保存するをご覧ください。 以下のアクティビティを使用して、製品版の品質を備えた堅牢なアプリを設計する方法を アーキテクチャ コンポーネントの組み合わせについては、以下をご覧ください。 アプリ アーキテクチャ ガイド
アクティビティのライフサイクルに関するコンセプト
アクティビティのライフサイクルのステージ間の遷移をナビゲートするために、
Activity
クラスは、次の 6 つのコールバックのコアセットを提供します。
onCreate()
,
onStart()
,
onResume()
,
onPause()
,
onStop()
、および
onDestroy()
。システムは
アクティビティが新しい状態になったときに呼び出す必要があります。
図 1 は、このパラダイムを視覚的に示しています。
![](https://developer.android.google.cn/guide/components/images/activity_lifecycle.png?authuser=9&hl=ja)
図 1. アクティビティのライフサイクルに関する簡略な図
ユーザーがアクティビティから離れる処理を開始すると、システムはアクティビティを解体するメソッドを呼び出します。一部のケースでは、インフラストラクチャの メモリに残っています(ユーザーが クリックします。このような場合、アクティビティはフォアグラウンドに戻ることができます。
ユーザーがアクティビティに戻ると、 ユーザーが中断したところから再開できますいくつかの例外を除き、アプリは 制限あり: アクティビティを起動するをご覧ください。
システムによる検出が プロセスとそれに含まれるアクティビティの強制終了は、状態 その時点のアクティビティの状態と状態の関係について詳しくは、 排除に対する脆弱性については、アクティビティ状態とメモリからの排除に関するセクションをご覧ください。
アクティビティの複雑さにもよりますが、すべてのライフサイクル メソッドを実装する必要はないと考えられます。ただし重要なのは それぞれの要素を理解し、アプリの動作に必要な要素を実装してください。 開発できます
ライフサイクル コールバック
このセクションでは、アクティビティのライフサイクルで使用されるコールバック メソッドの概念と実装について説明します。
一部のアクションは、アクティビティのライフサイクル メソッドに属します。ただし、 依存するコンポーネントのアクションを実装する コンポーネントを使用します。これを実現するには 依存するコンポーネントをライフサイクル対応にします。kubectl コマンドを ライフサイクル対応の依存関係コンポーネントについては、 ライフサイクル対応コンポーネントによるライフサイクルへの対応
onCreate()
このコールバックを実装する必要があります。このコールバックは、システムが最初にアクティビティを作成したときに呼び出されます。アクティビティが作成されると、アクティビティは作成済みの状態になります。
onCreate()
基本的なアプリケーション起動ロジックを実行し、
アクティビティの存続期間全体で 1 回だけ行われます。
たとえば、
onCreate()
の実装で、データをリストにバインドしたり、アクティビティを
ViewModel
,
クラススコープ変数をインスタンス化します。このメソッドは、
パラメータ savedInstanceState
(Bundle
)
アクティビティの以前に保存された状態を含むオブジェクト。アクティビティが
Bundle
オブジェクトの値は null になります。
インフラストラクチャのライフサイクルに接続されたライフサイクル対応コンポーネントを
受信すると、
ON_CREATE
イベントです。@OnLifecycleEvent
アノテーション付きのメソッドが呼び出されるため、ライフサイクル対応
コンポーネントは、作成された状態に必要なすべてのセットアップ コードを実行できます。
次の onCreate()
メソッドの例
ユーザー インターフェースの宣言など、アクティビティの基本的な設定を示します。
(XML レイアウト ファイルで定義される)、メンバー変数の定義、
見てみましょうこの例では、XML レイアウト ファイルは
ファイルのリソース ID R.layout.main_activity
を
setContentView()
。
Kotlin
lateinit var textView: TextView // Some transient state for the activity instance. var gameState: String? = null override fun onCreate(savedInstanceState: Bundle?) { // Call the superclass onCreate to complete the creation of // the activity, like the view hierarchy. super.onCreate(savedInstanceState) // Recover the instance state. gameState = savedInstanceState?.getString(GAME_STATE_KEY) // Set the user interface layout for this activity. // The layout is defined in the project res/layout/main_activity.xml file. setContentView(R.layout.main_activity) // Initialize member TextView so it is available later. textView = findViewById(R.id.text_view) } // This callback is called only when there is a saved instance previously saved using // onSaveInstanceState(). Some state is restored in onCreate(). Other state can optionally // be restored here, possibly usable after onStart() has completed. // The savedInstanceState Bundle is same as the one used in onCreate(). override fun onRestoreInstanceState(savedInstanceState: Bundle?) { textView.text = savedInstanceState?.getString(TEXT_VIEW_KEY) } // Invoked when the activity might be temporarily destroyed; save the instance state here. override fun onSaveInstanceState(outState: Bundle?) { outState?.run { putString(GAME_STATE_KEY, gameState) putString(TEXT_VIEW_KEY, textView.text.toString()) } // Call superclass to save any view hierarchy. super.onSaveInstanceState(outState) }
Java
TextView textView; // Some transient state for the activity instance. String gameState; @Override public void onCreate(Bundle savedInstanceState) { // Call the superclass onCreate to complete the creation of // the activity, like the view hierarchy. super.onCreate(savedInstanceState); // Recover the instance state. if (savedInstanceState != null) { gameState = savedInstanceState.getString(GAME_STATE_KEY); } // Set the user interface layout for this activity. // The layout is defined in the project res/layout/main_activity.xml file. setContentView(R.layout.main_activity); // Initialize member TextView so it is available later. textView = (TextView) findViewById(R.id.text_view); } // This callback is called only when there is a saved instance previously saved using // onSaveInstanceState(). Some state is restored in onCreate(). Other state can optionally // be restored here, possibly usable after onStart() has completed. // The savedInstanceState Bundle is same as the one used in onCreate(). @Override public void onRestoreInstanceState(Bundle savedInstanceState) { textView.setText(savedInstanceState.getString(TEXT_VIEW_KEY)); } // Invoked when the activity might be temporarily destroyed; save the instance state here. @Override public void onSaveInstanceState(Bundle outState) { outState.putString(GAME_STATE_KEY, gameState); outState.putString(TEXT_VIEW_KEY, textView.getText()); // Call superclass to save any view hierarchy. super.onSaveInstanceState(outState); }
XML ファイルを定義して setContentView()
に渡す代わりに、
アクティビティ コード内で新しい View
オブジェクトを作成し、
ビュー階層を作成し、新しい View
オブジェクトを
ViewGroup
。次に、そのレイアウトを使用するために、
ルート ViewGroup
を setContentView()
にします。
ユーザー インターフェースの作成について詳しくは、
ユーザー インターフェースのドキュメントをご覧ください。
アクティビティが [作成済み]
あります。onCreate()
メソッドの実行が終了すると、アクティビティは Started
システムが onStart()
を呼び出します。
および onResume()
メソッドを
あります。
onStart()
アクティビティが開始状態になると、システムは
onStart()
を呼び出します。
この呼び出しにより、アクティビティは
アプリは、アクティビティがフォアグラウンドに移ってインタラクティブになる準備をします。
たとえば、このメソッドでは、インフラストラクチャの
UI が初期化されます。
アクティビティが開始状態に移行すると、ライフサイクル対応コンポーネントが
アクティビティのライフサイクルに
ON_START
イベント。
onStart()
メソッドが完了します。
作成済み状態と同様に、アクティビティは破棄され、
トリガーされます。このコールバックが終了すると、アクティビティは
再開された状態で、システムが
onResume()
メソッドを使用します。
onResume()
アクティビティが再開状態になると、フォアグラウンドになり、
システムが onResume()
を呼び出します。
呼び出すことができます。これは、アプリがユーザーと対話する状態です。何かが起こるまで、アプリはこの状態のままになります。
電話を受けるデバイス、ユーザーがアプリから離れて
別のアクティビティに移動したり、デバイスの画面がオフになったりした場合。
アクティビティが再開状態に移行すると、ライフサイクル対応コンポーネントは
アクティビティのライフサイクルに
ON_RESUME
イベントです。この時点で、ライフサイクル コンポーネントは、コンポーネントが表示されフォアグラウンドにある状態で実行する必要がある機能(カメラ プレビューの開始など)を有効にできます。
割り込みイベントが発生すると、アクティビティは [一時停止中] ステータスになります。
システムによって
onPause()
コールバック。
アクティビティが
再開された状態になると、システムは再度
onResume()
メソッドを使用します。このため、
onResume()
: リリース中にリリースするコンポーネントを初期化する
onPause()
などのアクションは、
アクティビティが再開可能状態になるたびに
あります。
これは、カメラにアクセスするライフサイクル対応コンポーネントの例です。
コンポーネントは ON_RESUME
イベントを受信します。
Kotlin
class CameraComponent : LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun initializeCamera() { if (camera == null) { getCamera() } } ... }
Java
public class CameraComponent implements LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) public void initializeCamera() { if (camera == null) { getCamera(); } } ... }
上記のコードにより、カメラが初期化されると、
LifecycleObserver
ON_RESUME
イベントを受信します。ただしマルチウィンドウモードでは
広告が一時停止状態であっても完全に表示されることがありますたとえば
アプリがマルチウィンドウ モードになっているときに、マルチウィンドウ モードになっていないウィンドウをユーザーがタップした。
アクティビティを含むと、アクティビティは一時停止状態になります。
もし
アプリが再開(表示可能)の場合にのみカメラを有効にする
でアクティブな状態)になっていて、その後でカメラを初期化します。
ON_RESUME
件のイベント
見てみましょう。アクティビティの実行中にカメラをアクティブのままにする場合
一時停止しているが、マルチウィンドウ モードなどで表示されている場合は、
ON_START
イベント後にカメラを初期化します。
しかし カメラは アクティビティが一時停止されているときにカメラをアクティブにすると、別のデバイスでカメラへのアクセスが拒否されることがあります マルチウィンドウ モードでアプリを再開しました。場合によっては、コードを カメラはアクティブになりますが、 全体的なユーザーエクスペリエンスが向上します。
このため、データのどの部分を ライフサイクル ライフサイクルの中では、共有システム リソースを コンテキストに基づいて生成されます。マルチウィンドウのサポートに関する詳細 マルチウィンドウのサポートをご覧ください。
初期化操作を実行するビルドアップ イベントの選択にかかわらず、対応するライフサイクル イベントを使用してリソースを解放してください。初期化の後に何かを初期化した場合、
ON_START
イベントがトリガーされた後で解放または終了します。
ON_STOP
イベント。もし
ON_RESUME
イベントの後で初期化し、
ON_PAUSE
イベント。
上記のコード スニペットでは、カメラの初期化コードを
ライフサイクル対応コンポーネントです。代わりに、このコードをアクティビティに直接挿入することもできます。
ライフサイクル コールバック(onStart()
や
onStop()
ですが、おすすめしません。このロジックを追加すると、
独立したライフサイクル対応コンポーネントに変換することで、そのコンポーネントを再利用できます。
コードを複製することなく複数のアクティビティに分散できます。ライフサイクル対応コンポーネントの作成方法については、以下をご覧ください。
ライフサイクル対応コンポーネントによるライフサイクルへの対応
onPause()
ユーザーが離脱したことを示す最初の通知として、システムがこのメソッドを呼び出します。 ただし、必ずしもアクティビティが破棄されることを意味するわけではありません。 これは、アクティビティがフォアグラウンドにないことを示していますが、 ユーザーがマルチウィンドウ モードの場合でも引き続き表示されます。 アクティビティが開始される理由はいくつかあります。 次のような状態です。
- アプリの実行を中断するイベント。 onResume() コールバックが呼び出されると、現在のアクティビティを一時停止します。これは最も一般的なケースです。
- マルチウィンドウ モードで、1 つのアプリのみがフォーカスされている 他のすべてのアプリは一時停止します。
- ダイアログなどの新しい半透明アクティビティを開く。 対象となるアクティビティを一時停止します。限りにおいて アクティビティは部分的に表示されているがフォーカスされていない場合、 一時停止したままになります
アクティビティが一時停止状態に移行すると、ライフサイクル対応コンポーネントが
アクティビティのライフサイクルに
ON_PAUSE
イベント。この時点でライフサイクル コンポーネントは、コンポーネントがフォアグラウンドにないときに実行する必要のない機能を停止できます(カメラ プレビューの停止など)。
onPause()
メソッドを使用して、一時停止または
継続できないオペレーションや、適度に継続する可能性のあるオペレーションを調整する場合、
Activity
が一時停止状態にあり
近日中に再開される見込みです
また、onPause()
メソッドを使用して、
システム リソース、センサー(GPS など)へのハンドル、または
アクティビティが一時停止されていて、ユーザーが
必要があります。
ただし、onResume()
に関するセクションで説明したように、一時停止中の
アプリがマルチウィンドウ モードの場合でも、アクティビティは完全に表示されることがあります。
完全にリリースまたは調整するには、onPause()
ではなく onStop()
の使用を検討してください
マルチウィンドウ モードのサポートを強化する UI 関連のリソースと操作。
次の LifecycleObserver
の例
ON_PAUSE
イベントに反応するのは、
ON_RESUME
イベントの例(初期化の後にカメラを解放する)
ON_RESUME
イベントを受信した場合:
Kotlin
class CameraComponent : LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) fun releaseCamera() { camera?.release() camera = null } ... }
Java
public class JavaCameraComponent implements LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) public void releaseCamera() { if (camera != null) { camera.release(); camera = null; } } ... }
この例では、カメラのリリースコードが
ON_PAUSE
イベントが LifecycleObserver
で受信される。
onPause()
の実行は非常に短く、
保存操作を実行するのに十分な時間が必ずしも得られるとは限りません。今回
onPause()
を使用してアプリケーションやユーザーの保存をしないでください。
ネットワーク呼び出しやデータベース トランザクションの実行など、さまざまなタスクを実行できます。そのような作業は
完了していない状態を表します。
代わりに、負荷の高いシャットダウン オペレーションを
onStop()
。詳細情報
実行に適したオペレーションについて
onStop()
については、次のセクションをご覧ください。保存と保存について詳しくは、
状態の保存と復元に関するセクションをご覧ください。
onPause()
メソッドが完了しても、アクティビティが一時停止状態でなくなるわけではありません。むしろ、このアクティビティは、
アクティビティが再開されるか、アクティビティが完全に
ユーザーには表示されません。アクティビティが再開すると、システムは再び
onResume()
コールバックを使用します。
もし
アクティビティが一時停止状態から再開状態に戻った場合、システムは
メモリに常駐する Activity
インスタンス、
システムが onResume()
を呼び出したときにそのインスタンスを取得します。
このシナリオでは、初期化または初期化中に作成されたコンポーネントを再初期化する必要はありません。
コールバック メソッド群が含まれます。アクティビティが
完全に見えない場合でも、システムは
onStop()
。
onStop()
アクティビティがユーザーに表示されないと、
停止状態になり、システムは
onStop()
コールバック。これは、新しく起動されたアクティビティが画面全体を覆う場合に発生します。「
システムは onStop()
も呼び出す
アクティビティの実行が終了し、終了しようとしているとき。
アクティビティが停止状態に移行すると、ライフサイクル対応コンポーネントは
アクティビティのライフサイクルに
ON_STOP
イベント。この時点で、ライフサイクル コンポーネントは、コンポーネントが画面に表示されていない間に実行する必要のない機能を停止できます。
onStop()
メソッドで、リリースまたは調整します。
アプリがユーザーに表示されない間は不要なリソースを管理します。たとえば、アプリがアニメーションを一時停止する場合や、高精度の位置情報アップデートから低精度の位置情報アップデートに切り替える場合です。使用
onStop()
を onPause()
から変更
ユーザーがマルチウィンドウでアクティビティを表示しても、UI 関連の処理が継続されることを意味します。
モードです。
また、onStop()
も使用します。
比較的多くの CPU 負荷の高いシャットダウン操作を実行できますたとえば
データベースに情報を保存するのに適した時間が
見つからず
onStop()
の間に行うことができます。下書きのメモの内容を永続ストレージに保存する onStop()
の実装例を次に示します。
Kotlin
override fun onStop() { // Call the superclass method first. super.onStop() // Save the note's current draft, because the activity is stopping // and we want to be sure the current note progress isn't lost. val values = ContentValues().apply { put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText()) put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle()) } // Do this update in background on an AsyncQueryHandler or equivalent. asyncQueryHandler.startUpdate( token, // int token to correlate calls null, // cookie, not used here uri, // The URI for the note to update. values, // The map of column names and new values to apply to them. null, // No SELECT criteria are used. null // No WHERE columns are used. ) }
Java
@Override protected void onStop() { // Call the superclass method first. super.onStop(); // Save the note's current draft, because the activity is stopping // and we want to be sure the current note progress isn't lost. ContentValues values = new ContentValues(); values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText()); values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle()); // Do this update in background on an AsyncQueryHandler or equivalent. asyncQueryHandler.startUpdate ( mToken, // int token to correlate calls null, // cookie, not used here uri, // The URI for the note to update. values, // The map of column names and new values to apply to them. null, // No SELECT criteria are used. null // No WHERE columns are used. ); }
上記のコードサンプルでは、SQLite を直接使用しています。ただし、Room を使用して、 SQLite に抽象化レイヤを提供する永続ライブラリです。学習内容 Room を使用するメリットとアプリに Room を実装する方法について詳しくは、 詳しくは、 Room 永続ライブラリ ご覧ください
アクティビティが停止状態になると、Activity
そのオブジェクトはメモリ内に常駐します。つまり、すべての状態と
ウィンドウ マネージャには関連付けられません。アクティビティが
その情報が呼び出されます
お客様による
コールバック メソッドの実行中に作成されたコンポーネントを再初期化する
自動的にシャットダウンしますシステムは最新の
レイアウト内の View
オブジェクトごとに状態が定義されています。そのため、
ユーザーが EditText
ウィジェットにテキストを入力すると、
コンテンツは保持されるので、保存して復元する必要はありません。
注: アクティビティを停止すると、システムはメモリを回復する必要がある場合に、アクティビティを含むプロセスを破棄することがあります。
アクティビティの実行中にシステムがプロセスを破棄しても、
停止しても、システムは View
の状態を保持します。
のオブジェクト(たとえば EditText
ウィジェット内のテキスト)
Bundle
- Key-Value ペアの blob。復元します。
ユーザーがアクティビティに戻った場合です。対象
ユーザーが戻ったアクティビティを復元する方法の詳細については、
状態の保存と復元に関するセクションをご覧ください。
停止状態のアクティビティは、その後ユーザーとやり取りするために戻るか、実行が終了して消滅します。アクティビティが戻ると、システムは onRestart()
を呼び出します。
Activity
の実行が終了すると、システムは以下を呼び出します。
onDestroy()
。
onDestroy()
onDestroy()
はアクティビティが破棄される前に呼び出されます。システムは、次のいずれかの理由でこのコールバックを呼び出します。
-
ユーザーが画面を完全に閉じたため、アクティビティは終了している
あるいは
finish()
が 呼び出されることになります。 - 設定により、システムがアクティビティを一時的に破棄しています デバイスの回転やマルチ ウィンドウ モードへの切り替えなどの操作を行えます。
アクティビティが破棄状態に移行すると、ライフサイクル対応コンポーネントは、
アクティビティのライフサイクルに
ON_DESTROY
イベント。ここで
ライフサイクル コンポーネントは、リリースされる前に
Activity
が破棄されます。
破棄される理由を判断するロジックを Activity
に挿入する代わりに、
ViewModel
オブジェクトを使用して
Activity
の関連するビューデータを確認できます。Activity
が再作成された場合
構成変更のため、ViewModel
は何も行う必要はありません。
保持され、次の Activity
インスタンスに渡されます。
Activity
が再作成されない場合、ViewModel
には
onCleared()
メソッドが呼び出され、
破棄する前に必要なデータをクリーンアップできます。この 2 つのシナリオは、
isFinishing()
メソッドを使用します。
アクティビティが終了している場合は、onDestroy()
が最後のライフサイクル コールバックになります。
受け取れます。構成の結果として onDestroy()
が呼び出された場合
変更すると、システムは新しいアクティビティのインスタンスをすぐに作成してから、
<ph type="x-smartling-placeholder"></ph>
onCreate()
新しい構成でその新しいインスタンスに
適用されます
onDestroy()
コールバックは、それ以前にリリースされていないすべてのリソースを解放する
コールバックを使用します(onStop()
など)。
アクティビティの状態とメモリからの退避
RAM を解放する必要がある場合、システムはプロセスを強制終了します。システムが動作する可能性は 特定のプロセスを強制終了するかどうかは、その時点でのプロセスの状態によって異なります。同様に、プロセスの状態は、プロセスで実行されているアクティビティの状態によって異なります。 表 1 は、プロセスの状態と活動の相関関係を示しています。 システムがプロセスを強制終了する可能性などです。この表は、プロセスが他の種類のリソースを実行していない場合にのみ 説明します。
強制終了の可能性 | プロセスの状態 | 最終的なアクティビティの状態 |
---|---|---|
最低 | フォアグラウンド(フォーカスがあるか、間もなくフォーカスを取得する) | 再開 |
低 | 表示(フォーカスなし) | 開始/一時停止 |
高め | 背景(非表示) | 停止中 |
最高 | なし | 破棄 |
表 1. プロセスのライフサイクルとアクティビティの状態の関係
システムがメモリを解放するためにアクティビティを直接強制終了することはありません。代わりに、 アクティビティが実行されるプロセスを強制終了し、アクティビティだけでなく プロセスで実行されている他のものも すべて含まれます保存する方法を システムによって開始されたプロセスが終了したときにアクティビティの UI の状態を復元する 状態の保存と復元に関するセクションをご覧ください。
ユーザーは、[設定] の [アプリケーション マネージャー] で 該当するアプリを強制終了します。
プロセスの詳細については、このモジュールの プロセスとスレッド 概要をご覧ください。
一時的な UI の状態の保存と復元
ユーザーは、構成変更(回転やマルチウィンドウ モードへの切り替えなど)全般にわたってアクティビティの UI の状態が変わらないことを想定します。ただし、そのような構成が存在する場合、アクティビティはデフォルトで破棄されます。 変更が発生し、アクティビティ インスタンスに保存されている UI の状態がすべてワイプされます。
同様に、ユーザーは一時的に別のアプリに切り替えてから元のアプリに戻った場合にも、UI の状態が同じままであることを想定します。ただし、システムがアプリのプロセスを破棄し、 ユーザーが外出し、アクティビティが停止します。
システム制約によってアクティビティが破棄された場合は、
ユーザーの一時的な UI 状態を、
ViewModel
<ph type="x-smartling-placeholder"></ph>
onSaveInstanceState()
、
ローカルストレージに保存されますシステムと比較したお客様の期待の詳細
複雑な UI 状態データを複数の環境で適切に維持する方法を
システムが開始したアクティビティとプロセスの終了については、をご覧ください。
UI の状態を保存する。
このセクションでは、インスタンスの状態の概要と、
onSaveInstance()
メソッド。アクティビティ自体に対するコールバックです。お使いの
UI データは軽量です。onSaveInstance()
のみを使用して UI を保持できます。
構成変更とシステムによって開始されたプロセスの終了の両方にわたって、常に状態を維持する必要があります。
ただし、onSaveInstance()
にはシリアル化/逆シリアル化の費用が発生するため、
ほとんどの場合、次のように ViewModel
と onSaveInstance()
の両方を使用します。
概要はをご覧ください
UI の状態を保存する。
注: 設定の変更について詳しくは、アクティビティを制限する方法をご確認ください。 構成変更に対応する方法についても説明しました。 システムと Jetpack Compose の詳細については、 構成の変更の処理ページ。
インスタンスの状態
通常のアプリの理由でアクティビティが破棄されるシナリオがいくつかあります。
動作(ユーザーが [戻る] ボタンを押したときやアクティビティなど)
呼び出すことによって、自身の破壊の合図を
finish()
メソッドを呼び出します。
ユーザーが [戻る] を押したためにアクティビティが破棄されたとき
アクティビティがそれ自体で終了した場合と、
その Activity
インスタンスが永久に失われることを意味します。対象
ユーザーの期待とシステムの動作が一致しており、
追加の作業が必要になります
ただし、システムの制約(
構成変更やメモリ プレッシャーなど)に関連している可能性がありますが、
Activity
インスタンスが消去されると、システムはその存在を記憶します。ユーザーがアクティビティに戻ろうとすると、システムはアクティビティが破棄された時点でのアクティビティの状態を記述する一連の保存済みデータを使用して、アクティビティの新しいインスタンスを作成します。
システムがデータの復元に使用する保存済みデータ。
以前の状態をインスタンス状態と呼びます。さまざまな
Bundle
オブジェクトに格納されている Key-Value ペア。デフォルトでは、
システムが Bundle
インスタンスの状態を使用して情報を保存する
次のように、アクティビティ レイアウトの各 View
オブジェクトについて確認できます。
ケースに入力されるテキスト値
EditText
ウィジェット。
そのため、アクティビティのインスタンスが破棄されてから再作成された場合、レイアウトの状態はコードを必要とすることなく以前の状態に復元されます。ただし、アクティビティには、アクティビティ内のユーザーの作業状況を追跡するメンバー変数など、復元する必要があると考えられる状態に関する情報が他にも含まれている場合があります。
注: Android システムがアクティビティのビューの状態を復元できるようにするには、各ビューに一意の ID が必要です。この ID は android:id
属性で指定します。
Bundle
オブジェクトは、それ以上の保持には適していません。
メインスレッドでシリアル化が必要であり、
システム プロセス メモリ少量よりも多くのデータを保存するには
永続ローカル クラウド ストレージを使用して、
storage、onSaveInstanceState()
メソッド、
ViewModel
クラス(を参照)
UI の状態を保存する。
onSaveInstanceState() を使用してシンプルで軽量な UI の状態を保存する
アクティビティの停止が開始されると、システムは onSaveInstanceState()
メソッドを呼び出します。これにより、アクティビティは状態情報をインスタンス状態バンドルに保存できます。このメソッドのデフォルトの実装では、EditText
ウィジェット内のテキストや ListView
ウィジェットのスクロール位置など、アクティビティのビュー階層の状態に関する一時的な情報が保存されます。
アクティビティの追加インスタンスの状態情報を保存するには、オーバーライドします
onSaveInstanceState()
保存する Bundle
オブジェクトに Key-Value ペアを追加します。
アクティビティが予期せず破棄された場合に備えて、オーバーライドすると、
onSaveInstanceState()
: スーパークラスの実装を呼び出す必要があります。
(デフォルトの実装でビュー階層の状態を保存する場合)
これを次の例に示します。
Kotlin
override fun onSaveInstanceState(outState: Bundle?) { // Save the user's current game state. outState?.run { putInt(STATE_SCORE, currentScore) putInt(STATE_LEVEL, currentLevel) } // Always call the superclass so it can save the view hierarchy state. super.onSaveInstanceState(outState) } companion object { val STATE_SCORE = "playerScore" val STATE_LEVEL = "playerLevel" }
Java
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, currentScore); savedInstanceState.putInt(STATE_LEVEL, currentLevel); // Always call the superclass so it can save the view hierarchy state. super.onSaveInstanceState(savedInstanceState); }
注:
onSaveInstanceState()
次を含まない
ユーザーがアクティビティを明示的に閉じたとき、または
finish()
が呼び出されます。
ユーザー設定やデータベースのデータなどの永続データを保存するには、
アクティビティがフォアグラウンドで実行されているときに適切な機会を得る。
このような機会が生じない場合は、契約期間中は永続データを保存してください。
onStop()
メソッドを使用します。
保存済みのインスタンスの状態を使用してアクティビティの UI の状態を復元する
以前に破棄したアクティビティを再作成する場合は、システムがアクティビティに渡した Bundle
から保存済みのインスタンスの状態を復元できます。また、
onCreate()
、
<ph type="x-smartling-placeholder"></ph>
onRestoreInstanceState()
Bundle
コールバック・メソッドは
インスタンスの状態に関する情報です。
onCreate()
メソッドは
システムがアクティビティの新しいインスタンスを作成しているかどうかが呼び出される
前の状態を再作成する場合は、状態 Bundle
が
null です。null の場合は、破棄された以前のインスタンスが復元されるのではなく、アクティビティの新しいインスタンスが作成されます。
次のコード スニペットは、一部の Pod を
onCreate()
内の状態データ:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Always call the superclass first // Check whether we're recreating a previously destroyed instance. if (savedInstanceState != null) { with(savedInstanceState) { // Restore value of members from saved state. currentScore = getInt(STATE_SCORE) currentLevel = getInt(STATE_LEVEL) } } else { // Probably initialize members with default values for a new instance. } // ... }
Java
@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. currentScore = savedInstanceState.getInt(STATE_SCORE); currentLevel = savedInstanceState.getInt(STATE_LEVEL); } else { // Probably initialize members with default values for a new instance. } // ... }
VM 内で状態を復元するのではなく、
onCreate()
は、
onRestoreInstanceState()
: これは
onStart()
メソッドを使用します。システムは
onRestoreInstanceState()
復元する保存済み状態がある場合だけです。
Bundle
が null かどうかを確認する必要はありません。
Kotlin
override fun onRestoreInstanceState(savedInstanceState: Bundle?) { // Always call the superclass so it can restore the view hierarchy. super.onRestoreInstanceState(savedInstanceState) // Restore state members from saved instance. savedInstanceState?.run { currentScore = getInt(STATE_SCORE) currentLevel = getInt(STATE_LEVEL) } }
Java
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. currentScore = savedInstanceState.getInt(STATE_SCORE); currentLevel = savedInstanceState.getInt(STATE_LEVEL); }
注意: 常にインスタンスのスーパークラス実装を呼び出してください。
onRestoreInstanceState()
そうすれば、デフォルトの実装でビュー階層の状態を復元できます。
アクティビティ間の移動
アクティビティの間、アプリはアクティビティの開始と終了を何回も繰り返す可能性があります。 (ユーザーがデバイスの [戻る] ボタンをタップしたときなど) または、そのアクティビティによって別のアクティビティを起動できます。
このセクションでは、アクティビティの適切な遷移を実装するうえで理解しておく必要があるトピックについて説明します。 これらのトピックには、別のアクティビティからのアクティビティの開始、アクティビティの状態の保存、アクティビティの状態の復元などがあります。
アクティビティを別のアクティビティから開始する
特定の時点で、アクティビティが別のアクティビティを開始する必要が生じることは頻繁にあります。たとえば、アプリが現在の画面から新しい画面に移動する必要がある場合に、この動作が必要です。
アクティビティが新しいアクティビティの結果を返す必要があるかどうかによる
新しいアクティビティを開始するには、
startActivity()
メソッドまたは
startActivityForResult()
メソッドを呼び出します。いずれの場合も、Intent
オブジェクトを渡します。
Intent
オブジェクトでは、
記述するか、実行するアクションの種類を記述します。
システムによって適切なアクティビティが自動的に選択されるため、
実行することもできます。Intent
オブジェクトには、開始したアクティビティで使用する少量のデータを含めることもできます。
Intent
クラスの詳細については、インテントとインテント フィルタをご覧ください。
startActivity()
新規に開始されたアクティビティから結果を返す必要がない場合、現在のアクティビティは startActivity()
メソッドを呼び出して新しいアクティビティを開始できます。
独自のアプリで作業する場合には、既知のアクティビティを起動するだけで済むことが頻繁にあります。
たとえば、次のコード スニペットは、SignInActivity
という名前のアクティビティを起動する方法を示しています。
Kotlin
val intent = Intent(this, SignInActivity::class.java) startActivity(intent)
Java
Intent intent = new Intent(this, SignInActivity.class); startActivity(intent);
アクティビティから取得したデータを使用して、アプリでメールやテキスト メッセージの送信、ステータスの更新などの操作を行うことが必要な場合もあります。 この場合、そのようなアクションを実行する独自のアクティビティがアプリに含まれていない可能性があります。 代わりに、デバイス上の他のアプリが提供するアクティビティを利用できます。 ユーザーに代わって操作を実行できます
そこで重要となるのがインテントです。新しい 実行するアクションを記述するインテント インテントがあると、システムが適切な アクティビティを検出できます。インテントを処理できるアクティビティが複数ある場合は、ユーザーが使用するアクティビティを選択できます。たとえば、ユーザーがメッセージを送信できるようにする場合は、 次のインテントを作成できます。
Kotlin
val intent = Intent(Intent.ACTION_SEND).apply { putExtra(Intent.EXTRA_EMAIL, recipientArray) } startActivity(intent)
Java
Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_EMAIL, recipientArray); startActivity(intent);
インテントに追加された EXTRA_EMAIL
エクストラは、
メールの送信先となるメールアドレスです。メールアプリケーションが
このインテントに応答すると、エクストラで提供された文字列配列を読み取り、
「to」にアドレスを配置します。フィールドに入力します。この
メール アプリケーションのアクティビティが開始され、ユーザーが操作を完了すると、
アクティビティの再開です。
startActivityForResult()
アクティビティの終了時に、アクティビティから結果を戻すことが必要な場合があります。たとえば
ユーザーが連絡先リストから人を選択できるアクティビティ。終了すると、
クリックします。そのためには、
startActivityForResult(Intent, int)
メソッドです。ここで、
整数パラメータで呼び出しを識別します。
この ID は、サービスに対する複数の呼び出しを区別するためのものです。
startActivityForResult(Intent, int)
割り当てることができます。グローバル識別子ではなく
他のアプリやアクティビティと競合するリスクがない。結果は
onActivityResult(int, int, Intent)
メソッドを呼び出します。
子アクティビティが終了すると、setResult(int)
を呼び出して親にデータを返すようにすることができます。
子アクティビティは、標準の結果である結果コードを提供する必要があります。
RESULT_CANCELED
、RESULT_OK
、または任意のカスタム値
RESULT_FIRST_USER
より。
また
子アクティビティは、必要に応じて Intent
を返すことができます。
必要な追加データを含むオブジェクトです。親アクティビティは
onActivityResult(int, int, Intent)
メソッドに整数の識別子を添えて、親アクティビティが元々
情報を受け取れます
クラッシュなど、なんらかの原因で子アクティビティが失敗すると、親アクティビティはコード RESULT_CANCELED
の結果を受け取ります。
Kotlin
class MyActivity : Activity() { // ... override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { // When the user center presses, let them pick a contact. startActivityForResult( Intent(Intent.ACTION_PICK,Uri.parse("content://contacts")), PICK_CONTACT_REQUEST) return true } return false } override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) { when (requestCode) { PICK_CONTACT_REQUEST -> if (resultCode == RESULT_OK) { // A contact was picked. Display it to the user. startActivity(Intent(Intent.ACTION_VIEW, intent?.data)) } } } companion object { internal val PICK_CONTACT_REQUEST = 0 } }
Java
public class MyActivity extends Activity { // ... static final int PICK_CONTACT_REQUEST = 0; public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { // When the user center presses, let them pick a contact. startActivityForResult( new Intent(Intent.ACTION_PICK, new Uri("content://contacts")), PICK_CONTACT_REQUEST); return true; } return false; } protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PICK_CONTACT_REQUEST) { if (resultCode == RESULT_OK) { // A contact was picked. Display it to the user. startActivity(new Intent(Intent.ACTION_VIEW, data)); } } } }
アクティビティを連携させる
あるアクティビティが別のアクティビティを開始すると、双方でライフサイクルの遷移が発生します。 最初のアクティビティが動作を停止して、一時停止状態または停止状態となり、もう 1 つのアクティビティが作成されます。これらのアクティビティでディスクなどに保存されているデータを共有している場合は、2 つ目のアクティビティが作成される前に最初のアクティビティが完全に停止することはない点を理解しておくことが重要です。むしろ、2 つ目のアクティビティを開始するプロセスは、最初のアクティビティを停止するプロセスと重複します。
ライフサイクル コールバックの順序は、特に 2 つのアクティビティが 同じプロセス(つまり同じアプリ)内で実行され、一方が他方を起動している場合です。アクティビティ A がアクティビティ B を開始する場合の動作の順序は次のとおりです。
- アクティビティ A の
onPause()
メソッドが実行されます。 - アクティビティ B の
onCreate()
、onStart()
、onResume()
の各メソッドが順次実行されます アクティビティ B にユーザー フォーカスが移動しました。 - アクティビティ A が画面に表示されなくなると、その
onStop()
メソッドが実行されます。
このライフサイクル コールバックにより、アプリケーションの 情報をやり取りできます。