ユーザーがアプリ内を移動したり、アプリから離れたり、アプリに戻ったりすると、アプリ内の Activity インスタンスは、ライフサイクルのさまざまな状態に遷移します。Activity クラスには、状態が変化したとき、システムがアクティビティを作成、停止、再開したとき、アクティビティが存在するプロセスを破棄したときに、アクティビティに通知するコールバックが多数用意されています。
ライフサイクル コールバック メソッド内で、ユーザーがアクティビティを離れて再び戻ってきたときのアクティビティの動作を宣言できます。たとえば、ストリーミング動画プレーヤーを構築している場合、ユーザーが別のアプリに切り替えたときに、動画を一時停止してネットワーク接続を終了できます。ユーザーが戻ってきたら、ネットワークに再接続して、ユーザーが同じ場所から動画を再開できるようにします。
各コールバックを使用すると、特定の状態変化に適した特定の処理を実行できます。適切なタイミングで適切な処理を行い、遷移を適切に処理することで、アプリの堅牢性とパフォーマンスが向上します。たとえば、ライフサイクル コールバックを適切に実装すると、アプリで次のような問題を回避できます。
- アプリの使用中にユーザーが電話を受けたり、別のアプリに切り替えたりすると、クラッシュする。
- ユーザーがアプリをアクティブに使用していないときに、貴重なシステム リソースを消費する。
- ユーザーがアプリを離れて後で戻ってきたときに、ユーザーの進捗状況が失われる。
- 画面が横向きと縦向きの間で回転したときに、クラッシュしたり、ユーザーの進行状況が失われたりする。
このドキュメントでは、アクティビティのライフサイクルについて詳しく説明します。このドキュメントでは、まずライフサイクル パラダイムについて説明します。次に、各コールバックについて説明します。コールバックの実行中に内部で何が起こるか、コールバック中に何を実装する必要があるかについて説明します。
次に、アクティビティの状態と、システムによって強制終了されるプロセスの脆弱性との関係について簡単に説明します。最後に、アクティビティの状態間の遷移に関連するいくつかのトピックについて説明します。
ベスト プラクティスに関するガイダンスなど、ライフサイクルの処理については、Jetpack Compose のライフサイクルと UI の状態を保存するをご覧ください。アクティビティとアーキテクチャ コンポーネントを組み合わせて、堅牢な製品版品質のアプリを設計する方法については、アプリ アーキテクチャ ガイドをご覧ください。
アクティビティのライフサイクルに関するコンセプト
アクティビティのライフサイクルのステージ間の遷移をナビゲートするために、Activity クラスには onCreate、onStart、onResume、onPause、onStop、onDestroy という 6 つのコールバックのコアセットが用意されています。アクティビティが新しい状態に移行すると、システムはこれらのコールバックを呼び出します。
図 1 は、このパラダイムを視覚的に表したものです。
ユーザーがアクティビティから離れ始めると、システムはアクティビティを破棄するメソッドを呼び出します。ユーザーが別のアプリに切り替えた場合など、アクティビティが部分的にのみ破棄され、メモリ内に残っていることがあります。このような場合、アクティビティはフォアグラウンドに戻ることができます。
ユーザーがアクティビティに戻ると、中断したところから再開されます。いくつかの例外を除き、アプリはバックグラウンドで実行されているときにアクティビティを開始することが制限されています。
システムが特定のアクティビティとそのアクティビティ内のプロセスを強制終了する可能性は、その時点でのアクティビティの状態によって異なります。状態と強制終了の可能性の関係について詳しくは、アクティビティの状態とメモリからの強制終了をご覧ください。
アクティビティの複雑さにもよりますが、すべてのライフサイクル メソッドを実装する必要はないと考えられます。ただし、それぞれを理解し、ユーザーが期待する動作をアプリが実現できるように実装することが重要です。
Compose とライフサイクル
Compose では、onStart や onResume などのアクティビティ コールバック内にビジネス ロジックや手動のオブザーバー設定を直接配置しないでください。代わりに、Lifecycle 対応のエフェクトと状態対応のオブザーバーを使用します。これらは、画面上の UI の存在に自動的に合わせられます。
- ライフサイクル対応の収集:
collectAsStateWithLifecycleを使用して、ViewModelからフローを消費します。この API は、UI が Started 状態になると自動的に収集を開始し、バックグラウンドに移行すると停止するため、不要なリソース消費を防ぐことができます。フローを状態として収集した後、LifecycleEffectsを使用して、ライフサイクル イベントが発生したときにコードを実行できます。 - ロジックのフロー: これらの API を使用すると、UI はコンポジション ツリーを介してライフサイクル状態に自然に反応し、ユーザーがコンポーネントをアクティブに操作しているときにのみビジネス ロジックが実行されるようになります。
Compose とライフサイクルの詳細については、Jetpack Compose のライフサイクルをご覧ください。
ライフサイクル コールバック
このセクションでは、アクティビティのライフサイクルで使用されるコールバック メソッドのコンセプトと実装について説明します。
一部のアクションは、アクティビティのライフサイクル メソッドに属します。ただし、従属関係にあるコンポーネントのアクションを実装するコードは、アクティビティのライフサイクル メソッドではなく、コンポーネントに配置します。これを実現するには、依存コンポーネントをライフサイクル対応にする必要があります。依存コンポーネントをライフサイクル対応にする方法については、Jetpack Compose のライフサイクルをご覧ください。
onCreate
このコールバックを実装する必要があります。このコールバックは、システムが最初にアクティビティを作成したときに呼び出されます。アクティビティが作成されると、アクティビティは作成済み状態になります。onCreate メソッドでは、アクティビティのライフサイクル全体で 1 回だけ発生する基本的なアプリケーション起動ロジックを実行します。
たとえば、onCreate の実装では、データをリストにバインドし、アクティビティを ViewModel に関連付け、いくつかのクラススコープ変数をインスタンス化します。このメソッドは、パラメータ savedInstanceState を受け取ります。これは、アクティビティの以前に保存された状態を含む Bundle オブジェクトです。アクティビティが以前に存在したことがない場合、Bundle オブジェクトの値は null です。
アクティビティのライフサイクルに接続されているライフサイクル対応コンポーネントがある場合、そのコンポーネントは ON_CREATE イベントを受け取ります。@OnLifecycleEvent アノテーションが付けられたメソッドが呼び出され、ライフサイクル対応コンポーネントは、作成された状態に必要なセットアップ コードを実行できます。
次の例は、最小限のアクティビティに Text コンポーザブルを統合する方法を示しています。
class ExampleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { // In here, we can call composables! MaterialTheme { Greeting(name = "compose") } } } } @Composable fun Greeting(name: String) { Text(text = "Hello $name!") }
アクティビティは Created 状態のままにはなりません。onCreate メソッドの実行が完了すると、アクティビティは「開始」状態になり、システムは onStart メソッドと onResume メソッドを連続して呼び出します。
onStart
アクティビティが「開始」状態になると、システムは onStart を呼び出します。この呼び出しにより、アプリがアクティビティをフォアグラウンドに移行してインタラクティブにする準備を整えるため、アクティビティがユーザーに表示されます。たとえば、このメソッドは、UI を維持するコードが初期化される場所です。
アクティビティが「開始」状態に移行すると、アクティビティのライフサイクルに関連付けられているライフサイクル対応コンポーネントは ON_START イベントを受け取ります。
onStart メソッドはすぐに完了し、Created 状態と同様に、アクティビティは Started 状態のままになりません。このコールバックが完了すると、アクティビティは再開状態になり、システムは onResume メソッドを呼び出します。
onResume
アクティビティが再開状態になると、フォアグラウンドに移動し、システムが onResume コールバックを呼び出します。これは、アプリがユーザーと対話する状態です。アプリは、デバイスが電話を受ける、ユーザーが別のアクティビティに移動する、デバイスの画面がオフになるなど、アプリからフォーカスが外れるまで、この状態を維持します。
アクティビティが再開状態に移行すると、アクティビティのライフサイクルに関連付けられているライフサイクル対応コンポーネントは ON_RESUME イベントを受け取ります。このメソッドでは、ライフサイクル コンポーネントは、コンポーネントがフォアグラウンドに表示されている間に実行する必要がある機能(カメラ プレビューの開始など)を有効にできます。
割り込みイベントが発生すると、アクティビティは一時停止状態になり、システムは onPause コールバックを呼び出します。
アクティビティが一時停止状態から再開状態に戻ると、システムは再び onResume メソッドを呼び出します。そのため、onResume を実装して、onPause で解放するコンポーネントを初期化し、アクティビティが再開状態になるたびに発生する必要があるその他の初期化を実行します。
以下に、コンポーネントが ON_RESUME イベントを受け取ったときにカメラにアクセスする、ライフサイクル対応コンポーネントの例を示します。
class CameraComponent : LifecycleObserver {
...
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun initializeCamera() {
if (camera == null) {
getCamera()
}
}
...
}
上記のコードでは、LifecycleObserver が ON_RESUME イベントを受信すると、カメラが初期化されます。ただし、マルチ ウィンドウ モードでは、アクティビティが一時停止状態であっても完全に表示されることがあります。たとえば、アプリがマルチ ウィンドウ モードで、ユーザーがアクティビティを含まないウィンドウをタップすると、アクティビティは一時停止状態に移行します。
アプリが再開されたとき(フォアグラウンドで表示され、アクティブになったとき)にのみカメラをアクティブにする場合は、前述の ON_RESUME イベントの後にカメラを初期化します。アクティビティが一時停止しているが、マルチウィンドウ モードなどで表示されているときにカメラをアクティブな状態に保つ場合は、ON_START イベントの後にカメラを初期化します。
ただし、アクティビティが一時停止されているときにカメラをアクティブにすると、マルチウィンドウ モードで再開された別のアクティビティがカメラにアクセスできなくなる可能性があります。アクティビティが一時停止している間もカメラをアクティブにしておくことが必要な場合もありますが、そうすると、全体的なユーザー エクスペリエンスが低下する可能性があります。
このため、マルチウィンドウ モードのコンテキストで、共有システム リソースの制御を取得するのに最も適切なライフサイクルの場所を慎重に検討してください。マルチウィンドウ モードのサポートについて詳しくは、マルチウィンドウ モードのサポートをご覧ください。
初期化オペレーションを実行するビルドアップ イベントの選択にかかわらず、対応するライフサイクル イベントを使用してリソースを解放してください。ON_START イベントの後に何かを初期化する場合は、ON_STOP イベントの後にリリースまたは終了します。ON_RESUME イベントの後に初期化する場合は、ON_PAUSE イベントの後に解放します。
上記のコード スニペットでは、カメラの初期化コードをライフサイクル対応コンポーネントに配置しています。このコードを onStart や onStop などのアクティビティのライフサイクル コールバックに直接配置することもできますが、おすすめしません。このロジックを独立したライフサイクル対応コンポーネントに追加すると、コードを複製することなく、複数のアクティビティでコンポーネントを再利用できます。ライフサイクル対応コンポーネントを作成する方法については、Jetpack Compose のライフサイクルをご覧ください。
onPause
このメソッドは、ユーザーがアクティビティを離れることを示す最初の兆候として呼び出されますが、必ずしもアクティビティが破棄されることを意味するわけではありません。これは、アクティビティがフォアグラウンドではなくなったことを示しますが、ユーザーがマルチウィンドウ モードの場合は引き続き表示されます。アクティビティがこの状態になる理由はいくつかあります。
onResumeコールバックのセクションで説明したように、アプリの実行を中断するイベントが発生すると、現在のアクティビティが一時停止します。これが最も一般的なケースです。- マルチ ウィンドウ モードでは、一度に 1 つのアプリのみがフォーカスされ、システムは他のすべてのアプリを一時停止します。
- ダイアログなど、新しい半透明のアクティビティが開くと、そのアクティビティが覆うアクティビティは一時停止します。アクティビティは、部分的に表示されているもののフォーカスされていない限り、一時停止状態のままになります。
アクティビティが一時停止状態に移行すると、アクティビティのライフサイクルに関連付けられているライフサイクル対応コンポーネントは ON_PAUSE イベントを受け取ります。ここで、ライフサイクル コンポーネントは、コンポーネントがフォアグラウンドにないときに実行する必要のない機能(カメラ プレビューの停止など)を停止できます。
onPause メソッドを使用して、Activity が一時停止状態のときに続行できない、または適度に続行できるオペレーションを一時停止または調整します。これらのオペレーションは、すぐに再開されることが想定されます。
また、onPause メソッドを使用して、アクティビティが一時停止中でユーザーがそれらを必要としない場合に、システム リソース、センサー(GPS など)へのハンドル、バッテリー駆動時間に影響するリソースを解放することもできます。
ただし、onResume に関するセクションで説明したように、アプリがマルチ ウィンドウ モードの場合、一時停止中のアクティビティが完全に表示されたままになることがあります。マルチ ウィンドウ モードをより適切にサポートするには、onPause ではなく onStop を使用して、UI 関連のリソースとオペレーションを完全に解放または調整することを検討してください。
次の例では、ON_PAUSE イベントに反応する LifecycleObserver が、前述の ON_RESUME イベントの例に対応し、ON_RESUME イベントの受信後に初期化されるカメラを解放します。
class CameraComponent : LifecycleObserver {
...
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun releaseCamera() {
camera?.release()
camera = null
}
...
}
この例では、LifecycleObserver が ON_PAUSE イベントを受信した後にカメラのリリースコードを配置しています。
onPause の実行は非常に短時間であるため、保存オペレーションを実行するのに十分な時間があるとは限りません。このため、onPause を使用して、アプリデータやユーザーデータの保存、ネットワーク呼び出し、データベース トランザクションの実行は行わないでください。このような作業は、メソッドが完了する前に完了しない場合があります。
代わりに、onStop の間に負荷の高いシャットダウン オペレーションを実行します。onStop 中に実行する適切なオペレーションの詳細については、次のセクションをご覧ください。データの保存について詳しくは、状態の保存と復元をご覧ください。
onPause メソッドが完了しても、アクティビティが一時停止状態から抜けるわけではありません。アクティビティは、再開されるか、ユーザーに完全に表示されなくなるまで、この状態のままになります。アクティビティが再開されると、システムは再び onResume コールバックを呼び出します。
アクティビティが一時停止状態から再開状態に戻ると、システムは Activity インスタンスをメモリに保持し、システムが onResume を呼び出すときにそのインスタンスを呼び出します。このシナリオでは、再開状態に至るまでのコールバック メソッド中に作成されたコンポーネントを再初期化する必要はありません。アクティビティが完全に表示されなくなると、システムは onStop を呼び出します。
onStop
アクティビティがユーザーに表示されなくなると、アクティビティは停止状態になり、システムは onStop コールバックを呼び出します。これは、新しく起動されたアクティビティが画面全体を覆っている場合に発生することがあります。また、アクティビティの実行が終了して、アクティビティが終了しようとしているときにも、システムは onStop を呼び出します。
アクティビティが停止状態に移行すると、アクティビティのライフサイクルに関連付けられているライフサイクル対応コンポーネントは ON_STOP イベントを受け取ります。ここで、ライフサイクル コンポーネントは、コンポーネントが画面に表示されていないときに実行する必要のない機能を停止できます。
onStop メソッドでは、アプリがユーザーに表示されていないときに不要なリソースを解放または調整します。たとえば、アプリでアニメーションを一時停止したり、詳細な位置情報の更新から大まかな位置情報の更新に切り替えたりできます。onPause の代わりに onStop を使用すると、ユーザーがマルチウィンドウ モードでアクティビティを表示している場合でも、UI 関連の処理が続行されます。
また、onStop を使用して、比較的 CPU 負荷の高いシャットダウン オペレーションを実行します。たとえば、データベースに情報を保存するのに適したタイミングが見つからない場合は、onStop 中に保存できます。次の例は、下書きメモの内容を永続ストレージに保存する onStop の実装を示しています。
override fun onStop() {
super.onStop()
// Delegate the save operation to the ViewModel, which handles the
// background thread operations (e.g., using Kotlin Coroutines and Room).
noteViewModel.saveDraft()
}
アクティビティが停止状態になると、Activity オブジェクトはメモリに常駐したままになります。すべての状態とメンバー情報は保持されますが、ウィンドウ マネージャーにはアタッチされません。アクティビティが再開されると、この情報が呼び出されます。
停止状態のアクティビティは、その後ユーザーとやり取りするために戻るか、実行が終了して消滅します。アクティビティが再開されると、システムは onRestart を呼び出します。Activity の実行が終了すると、システムは onDestroy を呼び出します。
onDestroy
onDestroy は、アクティビティが破棄される前に呼び出されます。システムがこのコールバックを呼び出す理由は、次の 2 つのいずれかです。
- ユーザーがアクティビティを完全に終了したか、アクティビティで
finishが呼び出されたため、アクティビティが終了しています。 - デバイスの回転やマルチウィンドウ モードへの切り替えなど、構成の変更により、システムがアクティビティを一時的に破棄している。
アクティビティが破棄状態に移行すると、アクティビティのライフサイクルに関連付けられているライフサイクル対応コンポーネントは ON_DESTROY イベントを受け取ります。ここで、ライフサイクル コンポーネントは、Activity が破棄される前に必要なクリーンアップを行うことができます。
が破棄
される理由を判断するロジックを Activity に配置するのではなく、ViewModel オブジェクトを使用して、Activity に
関連するビューデータを格納します。構成の変更により Activity が再作成された場合、
ViewModel は何もする必要がありません。 は保持され、
次の Activity インスタンスに渡されるためです。
Activity が再作成されない場合、ViewModel は onCleared メソッドを呼び出し、破棄される前に必要なデータをクリーンアップできます。この 2 つのシナリオは、isFinishing メソッドで区別できます。
アクティビティが終了する場合、onDestroy はアクティビティが受け取る最後のライフサイクル コールバックです。構成の変更の結果として onDestroy が呼び出された場合、システムはすぐに新しいアクティビティ インスタンスを作成し、新しい構成でその新しいインスタンスに対して onCreate を呼び出します。
onDestroy コールバックは、onStop など、以前のコールバックで解放されなかったすべてのリソースを解放します。
アクティビティの状態とメモリからの退避
システムは、RAM を解放する必要があるときにプロセスを強制終了します。システムが特定のプロセスを強制終了する可能性は、その時点でのプロセスの状態によって異なります。プロセスの状態は、プロセスで実行されているアクティビティの状態によって異なります。表 1 は、プロセス状態、アクティビティ状態、システムがプロセスを強制終了する可能性の相関関係を示しています。この表は、プロセスが他のタイプのアプリケーション コンポーネントを実行していない場合にのみ適用されます。
強制終了の可能性 |
プロセスの状態 |
最終的なアクティビティの状態 |
最低 |
フォアグラウンド(フォーカスがあるか、間もなくフォーカスを取得する) |
再開 |
低 |
表示(フォーカスなし) |
開始/一時停止 |
高い |
背景(非表示) |
停止 |
最高 |
空白 |
破棄 |
表 1. プロセス ライフサイクルとアクティビティの状態の関係。
システムがメモリを解放するためにアクティビティを直接強制終了することはありません。代わりに、アクティビティが実行されているプロセスを強制終了し、アクティビティだけでなく、プロセスで実行されている他のすべてのものも破棄します。システムによって開始されたプロセスの終了が発生したときにアクティビティの UI の状態を保持、復元する方法については、状態の保存と復元に関するセクションをご覧ください。
ユーザーは、[設定] のアプリケーション マネージャーを使用して、対応するアプリを強制終了することで、プロセスを強制終了することもできます。
プロセスの詳細については、プロセスとスレッドの概要をご覧ください。
一時的な UI の状態の保存と復元
ユーザーが期待するのは、構成の変更後も、たとえば回転やマルチウィンドウ モードへの切り替えが行われてもアクティビティの UI の状態が変わらないことです。しかし、デフォルトでは、そうした構成の変更後にアクティビティは破棄され、アクティビティ インスタンスに保存されている UI の状態はすべてワイプされます。
同様に、ユーザーが一時的に別のアプリに切り替えた後に元のアプリに戻ってきたときも、UI の状態が変わっていないことを期待します。ただし、ユーザーがアプリを離れ、アクティビティが停止している間に、システムがアプリのプロセスを破棄することがあります。
システム制約によってアクティビティが破棄された場合は、ViewModel(複雑なビジネス ロジックと画面状態用)、Jetpack Compose の rememberSaveable API(軽量な UI 状態用)、ローカル ストレージを組み合わせて、ユーザーの一時的な UI 状態を保持します。ユーザーの期待とシステムの動作の比較、およびシステムによって開始されたアクティビティとプロセスの終了をまたいで複雑な UI 状態データを最適に保持する方法について詳しくは、UI の状態を保存するをご覧ください。
rememberSaveable は、内部で状態をバンドルすることで、構成変更とシステムによって開始されたプロセスの終了の両方を自動的に乗り越え、アクティビティ レベルのボイラープレートを必要とせずにシームレスなエクスペリエンスを提供します。
インスタンスの状態
ユーザーが戻るボタンを押した場合や、アクティビティが finish メソッドを呼び出して自身の破棄を通知した場合など、通常のアプリの動作によってアクティビティが破棄されるシナリオがいくつかあります。
ユーザーが戻るボタンを押したか、アクティビティ自体が終了したためにアクティビティが破棄されると、システムとユーザーの両方の Activity インスタンスのコンセプトが完全に失われます。このようなシナリオでは、ユーザーの期待とシステムの動作が一致するため、追加の作業は必要ありません。
ただし、システム上の制約(構成の変更やメモリの負荷など)によりシステムがアクティビティを破棄した場合、実際の Activity インスタンスはなくなりますが、システムはそれが存在していたことを記憶しています。ユーザーがアクティビティに戻ろうとすると、システムは、破棄されたときのアクティビティの状態を記述する一連の保存済みデータを使用して、そのアクティビティの新しいインスタンスを作成します。
システムが以前の状態を復元するために使用する保存済みデータは、インスタンスの状態と呼ばれます。内部的には、Key-Value ペアのコレクションです。デフォルトでは、システムはインスタンスの状態を使用して、ユーザーのテキスト入力やスクロール位置など、UI レイアウトに関する基本情報を保存します。
このシステム動作にフックするには、rememberSaveable を使用します。アクティビティ インスタンスが破棄されて再作成されると、rememberSaveable でラップされた UI 状態は自動的に復元されます。アクティビティ レベルのコードを追加する必要はありません。
ただし、アクティビティには、ユーザーデータ、ネットワーク レスポンス、ユーザーの進行状況を追跡するメンバー変数など、復元する必要があるより複雑な状態情報が含まれている可能性があります。インスタンスの状態メカニズム(ひいては rememberSaveable)は、メインスレッドでのシリアル化が必要であり、システム プロセスのメモリを消費するため、大量のデータを保持するのには適していません。
ごく少量のデータ以外を保持するには、UI の状態を保存するで説明されているように、永続的なローカル ストレージ、ViewModel クラス、Compose の状態ホイスティングを組み合わせて使用します。
rememberSaveable を使用して、シンプルで軽量な UI 状態を保存する
アクティビティが停止し始めると、システムは状態情報をインスタンス状態バンドルに保存する準備をします。このシステム動作にフックするには、コンポーズ可能な関数内で rememberSaveable を直接使用します。rememberSaveable は、アクティビティの再作成時に、ユーザーのテキスト入力やスクロール位置など、一時的な UI の状態を自動的に保存して復元します。
カスタムの軽量な状態情報(ゲームでのユーザーの進行状況など)を保存するには、rememberSaveable を使用して状態を宣言します。Compose フレームワークは、内部でインスタンス状態バンドルへのシリアル化を処理します。
var userTypedQuery by rememberSaveable(typedQuery, stateSaver = TextFieldValue.Saver) { mutableStateOf( TextFieldValue(text = typedQuery, selection = TextRange(typedQuery.length)) ) }
ユーザー設定やデータベースのデータなどの永続データを保存するには、アクティビティがフォアグラウンドにあるときに適切な機会を利用します。そのような機会がない場合は、onStop メソッドの実行中に永続データを保存します。
保存済みのインスタンスの状態を使用してアクティビティの UI の状態を復元する
以前に破棄されたアクティビティが再作成されると、状態の復元が自動的に行われます。rememberSaveable を使用すると、明示的な復元ロジックを記述したり、null バンドルを確認したり、アクティビティ コールバックをオーバーライドしたりする必要がなくなります。状態を初期化して保存するコードは、アクティビティが再開されたときに状態をシームレスに復元します。
var userTypedQuery by rememberSaveable(typedQuery, stateSaver = TextFieldValue.Saver) { mutableStateOf( TextFieldValue(text = typedQuery, selection = TextRange(typedQuery.length)) ) }
アクティビティとナビゲーション
アプリは、ユーザーがデバイスの戻るボタンをタップしたり、新しいデスティネーションを選択したりするなど、そのライフタイム中に何度も画面間を遷移する可能性があります。最新の Android アプリは通常、単一アクティビティ アーキテクチャを使用します。画面ごとに新しい Activity を開始するのではなく、アプリは単一の Activity をホストし、Navigation コンポーネントを使用して、そのアクティビティ内のコンポーズ可能な画面を入れ替えます。
Compose ファーストの最新のナビゲーションを実装する方法については、Jetpack Compose の Navigation 3 ライブラリのガイドをご覧ください。
アクティビティを別のアクティビティから開始する
アクティビティは、ある時点で別のアクティビティを開始する必要がある場合があります。たとえば、アプリが現在の画面から新しい画面に移動する必要がある場合に、この必要性が生じます。
開始しようとしている新しいアクティビティから結果を返す必要があるかどうかに応じて、startActivity メソッドまたは startActivityForResult メソッドを使用して新しいアクティビティを開始します。どちらの場合も、Intent オブジェクトを渡します。
Intent オブジェクトは、開始するアクティビティを正確に指定するか、実行するアクションのタイプを記述します。システムは、適切なアクティビティを選択します。このアクティビティは、別のアプリケーションのアクティビティでもかまいません。Intent オブジェクトは、起動されたアクティビティで使用される少量のデータを運ぶこともできます。Intent クラスの詳細については、インテントとインテント フィルタをご覧ください。
startActivity
新しく開始されたアクティビティが結果を返す必要がない場合、現在のアクティビティは startActivity メソッドを呼び出すことで、そのアクティビティを開始できます。
独自のアプリ内で作業する場合、多くの場合、既知のアクティビティを起動するだけで済みます。たとえば、次のコード スニペットは、SignInActivity というアクティビティを起動する方法を示しています。
val context = LocalContext.current
Button(onClick = {
val intent = Intent(context, SignInActivity::class.java)
context.startActivity(intent)
}) {
Text("Sign In")
}
外部アクティビティの開始
アプリ内のナビゲーションは Navigation によって処理されますが、Activity が他のアクティビティを開始する必要が生じることもあります。これは通常、ウェブブラウザを開く、メールを送信する、写真を撮るなどの特定のアクションを実行するために、外部アプリを利用する場合に発生します。
これを行うには、Intent オブジェクトを使用して、実行するアクションのタイプを記述します。システムは、別のアプリから適切なアクティビティを起動します。
たとえば、ユーザーがメール メッセージを送信できるようにするには、次のようなインテントを作成します。
val intent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_EMAIL, recipientArray)
}
startActivity(intent)
外部アクティビティを起動して結果を取得する必要がある場合(カメラアプリに写真を撮影して画像を返すようリクエストする場合など)は、非推奨の startActivityForResult コールバックではなく、最新の Activity 結果 API を使用します。
アクティビティを連携させる
あるアクティビティが別のアクティビティを開始すると、双方でライフサイクルの遷移が発生します。 最初のアクティビティは動作を停止し、一時停止または停止状態になります。その間に、もう一方のアクティビティが作成されます。これらのアクティビティがディスクなどに保存されたデータを共有する場合、2 つ目のアクティビティが作成される前に 1 つ目のアクティビティが完全に停止するわけではないことを理解しておくことが重要です。2 つ目の起動プロセスは、1 つ目の停止プロセスと重複します。
ライフサイクル コールバックの順序は明確に定義されています。特に、2 つのアクティビティが同じプロセス(つまり同じアプリ)にあり、一方が他方を起動している場合は、アクティビティ A がアクティビティ B を開始するときに発生するオペレーションの順序は次のとおりです。
- アクティビティ A の
onPauseメソッドが実行されます。 - アクティビティ B の
onCreate、onStart、onResumeメソッドが順番に実行されます。アクティビティ B にユーザー フォーカスが移ります。 - アクティビティ A が画面に表示されなくなると、その
onStopメソッドが実行されます。
この一連のライフサイクル コールバックにより、あるアクティビティから別のアクティビティへの情報の移行を管理できます。
参考情報
アクティビティのライフサイクルについて詳しくは、以下の参考情報をご覧ください。