各 Fragment
インスタンスには独自のライフサイクルがあります。ユーザーがアプリ内の移動や、アプリの操作を行うと、フラグメントは追加、削除、画面の開始と終了の過程で、ライフサイクルのさまざまな状態を遷移します。
ライフサイクルを管理するために、Fragment
では LifecycleOwner
が実装されており、getLifecycle()
メソッドでアクセスできる Lifecycle
オブジェクトが公開されています。
想定される Lifecycle
の状態は、それぞれ Lifecycle.State
列挙型で表されます。
Lifecycle
の上に Fragment
をビルドすることで、ライフサイクル対応コンポーネントによるライフサイクルへの対応で利用可能な手法とクラスを使用できます。たとえば、ライフサイクル対応コンポーネントを使用して、デバイスの位置を画面に表示できます。このコンポーネントは、フラグメントがアクティブ状態になると自動的にリッスンを開始し、フラグメントが非アクティブ状態になると停止します。
Fragment
クラスは、LifecycleObserver
を使用しない代わりに、フラグメントのライフサイクルの各変更に対応するコールバック メソッドを含んでいます。このコールバック メソッドとしては、onCreate()
、onStart()
、onResume()
、onPause()
、onStop()
、onDestroy()
があります。
フラグメントのビューはフラグメントの Lifecycle
とは別に管理される Lifecycle
を持っています。フラグメントはそのビューの LifecycleOwner
を維持しており、getViewLifecycleOwner()
または getViewLifecycleOwnerLiveData()
を使用してアクセスされます。
ビューの Lifecycle
へのアクセスは、フラグメントのビューが存在する間だけライフサイクル対応コンポーネントがタスクを実行する(たとえば、単に画面に表示されている LiveData
を観察する)場合に役立ちます。
このトピックでは、Fragment
ライフサイクルについて詳しく説明します。ここでは、フラグメントのライフサイクル状態を決定するルールと、Lifecycle
状態とフラグメントのライフサイクル コールバックの関係について説明します。
フラグメントとフラグメント マネージャー
フラグメントは、インスタンス化されると INITIALIZED
状態になります。フラグメントがライフサイクル上の他の状態間を遷移できるようにするには、FragmentManager
に追加される必要があります。FragmentManager
は、フラグメントがどの状態にあるべきかを判断し、その状態に移行させるように機能します。
FragmentManager
は、フラグメントのライフサイクルだけでなく、フラグメントをそのホスト アクティビティにアタッチし、フラグメントが使用されなくなったときにデタッチする機能も果たします。Fragment
クラスには、onAttach()
と onDetach()
という 2 つのコールバック メソッドがあり、これらのイベントのいずれかが発生したときに処理を実行するようにオーバーライドできます。
フラグメントが FragmentManager
に追加され、ホスト アクティビティにアタッチされると、onAttach()
コールバックが呼び出されます。この時点でフラグメントはアクティブであり、ライフサイクル状態は FragmentManager
に管理されています。ここで、findFragmentById()
などの FragmentManager
メソッドがこのフラグメントを返します。
ライフサイクル状態の変更の前は、必ず onAttach()
が呼び出されます。
フラグメントが FragmentManager
から削除され、ホスト アクティビティからデタッチされると、onDetach()
コールバックが呼び出されます。このフラグメントはアクティブではなくなり、findFragmentById()
を使って取得できなくなります。
ライフサイクル状態の変更の後は、必ず onDetach()
が呼び出されます。
なお、これらのコールバックは、FragmentTransaction
メソッド attach()
と detach()
とは無関係です。
これらのメソッドについて詳しくは、フラグメント トランザクションをご覧ください。
フラグメント ライフサイクル状態とコールバック
フラグメントのライフサイクル状態を決定するときに、FragmentManager
は次の要素を考慮します。
- フラグメントの最大の状態は
FragmentManager
によって決まります。フラグメントは、FragmentManager
の状態よりも上位の状態には移行しません。 FragmentTransaction
の一部として、setMaxLifecycle()
を使用して、フラグメントの最大ライフサイクル状態を設定できます。- フラグメントのライフサイクル状態を親より高くすることはできません。たとえば、親フラグメントまたはアクティビティは、子フラグメントの前に開始する必要があります。同様に、親フラグメントまたはアクティビティの前に子フラグメントを停止する必要があります。
図 1 に、フラグメントの各 Lifecycle
状態、およびフラグメントのライフサイクル コールバックとフラグメントのビュー Lifecycle
それぞれとの関係を示します。
フラグメントは、そのライフサイクルが進むにつれて状態が上位または下位へ移行します。たとえば、バックスタックの一番上に追加されたフラグメントは、CREATED
、STARTED
、RESUMED
を順に経て上位へ移行します。逆に、フラグメントがバックスタックからポップされると、フラグメントの状態は RESUMED
、STARTED
、CREATED
を順に経て最後に DESTROYED
へと下位へ移行します。
上位状態への遷移
ライフサイクルの状態が上位へ移行すると、フラグメントはまず、その新しい状態に関連付けられているライフサイクル コールバックを呼び出します。このコールバックが終了すると、関連する Lifecycle.Event
がフラグメント Lifecycle
からオブザーバーに送信されます。その後にフラグメント ビュー Lifecycle
が続きます(インスタンス化されている場合)。
フラグメント CREATED
フラグメントは CREATED
状態に到達すると、FragmentManager
に追加されます(onAttach()
メソッドはすでに呼び出されています)。
この状態は、フラグメント自体に関連付けられている保存状態をフラグメントの SavedStateRegistry
を通じて復元するのに適した状態です。なお、この時点ではフラグメントのビューは作成されておらず、フラグメントのビューに関連付けられている状態はすべて、ビューが作成された後で復元されます。
この遷移により、onCreate()
コールバックが呼び出されます。このコールバックは、以前に onSaveInstanceState()
によって保存された状態を含む savedInstanceState
Bundle
引数も受け取ります。
savedInstanceState
は、フラグメントが初めて作成されたときに null
値を持ちますが、onSaveInstanceState()
をオーバーライドしていない場合でも、以降の再作成に対しては常に非 null 値になることに注意してください。詳しくは、フラグメントで状態を保存するをご覧ください。
フラグメント CREATED とビュー INITIALIZED
フラグメントのビュー Lifecycle
は、Fragment
が有効な View
インスタンスが提供している場合にのみ作成されます。ほとんどの場合、@LayoutId
を受け取るフラグメント コンストラクタを使用できます。これにより、ビューは適切なタイミングで自動的にインフレートされます。onCreateView()
をオーバーライドして、フラグメントのビューのインフレートや作成をプログラムで行うこともできます。
フラグメントのビューが非 null View
でインスタンス化されている場合に限り、その View
はフラグメントに設定され、getView()
を使用して取得されます。その後、getViewLifecycleOwnerLiveData()
はフラグメントのビューに対応する新しい INITIALIZED
LifecycleOwner
で更新されます。この時点で onViewCreated()
ライフサイクル コールバックも呼び出されます。
この状態は、ビューの初期状態を設定し、コールバックがフラグメントのビューを更新する LiveData
インスタンスの監視を開始するのに適した状態です。フラグメントのビューの RecyclerView
インスタンスや ViewPager2
インスタンスにアダプターを設定するのにも適しています。
フラグメントとビュー CREATED
フラグメントのビューが作成された後、以前のビューの状態が存在する場合はそれが復元され、ビューの Lifecycle
は CREATED
状態に移行します。またビュー ライフサイクル オーナーは ON_CREATE
イベントをオブザーバーに送信します。ここでは、フラグメントのビューに関連付けられている追加の状態を復元する必要があります。
この遷移により onViewStateRestored()
コールバックも呼び出されます。
フラグメントとビュー STARTED
ライフサイクル対応コンポーネントをフラグメントの STARTED
状態に関連付けることを強くおすすめします。この状態により、フラグメントのビューが作成されている場合はそのビューが利用可能になり、フラグメントの子 FragmentManager
で FragmentTransaction
を安全に実行できるようになります。フラグメントのビューが非 null である場合、フラグメントの Lifecycle
が STARTED
に移行するとすぐに、フラグメントのビュー Lifecycle
は STARTED
に移行します。
フラグメントが STARTED
になると、onStart()
コールバックが呼び出されます。
フラグメントとビュー RESUMED
フラグメントが表示されていると、Animator
エフェクトと Transition
エフェクトはすべて終了し、フラグメントはユーザーからの操作を受けられるようになります。フラグメントの Lifecycle
が RESUMED
状態に移行し、onResume()
コールバックが呼び出されます。
RESUMED
への遷移は、ユーザーがフラグメントを操作できるようになったことを示す適切なシグナルです。RESUMED
ではないフラグメントが、ビューに対するフォーカスを手動で設定したり、入力方法の表示の処理を試みたりしてはなりません。
下位状態への遷移
フラグメントが下位のライフサイクル状態に移行すると、関連する Lifecycle.Event
がフラグメントのビュー Lifecycle
によってオブザーバーに送信されます。その後にフラグメントの Lifecycle
が続きます(インスタンス化されている場合)。フラグメントのライフサイクル イベントが送信されると、フラグメントは関連するライフサイクル コールバックを呼び出します。
フラグメントとビュー STARTED
ユーザーがフラグメントを終了する際、フラグメントがまだ表示されている間は、フラグメントとそのビューの Lifecycle
が STARTED
状態に戻り、ON_PAUSE
イベントがオブザーバーに送信されます。次にこのフラグメントは、その onPause()
コールバックを呼び出します。
フラグメントとビュー CREATED
フラグメントが表示されなくなると、フラグメントとビューの Lifecycle
が CREATED
状態に移行し、ON_STOP
イベントがオブザーバーに送信されます。この状態遷移は、親アクティビティまたはフラグメントの停止だけでなく、親アクティビティまたはフラグメントによる状態の保存によってもトリガーされます。この動作により、フラグメントの状態が保存される前に ON_STOP
イベントが確実に呼び出されるようになります。したがって、ON_STOP
イベントは子 FragmentManager
で FragmentTransaction
を安全に実行できる最後のタイミングになります。
図 2 に示すように、onStop()
コールバックの順序と、onSaveInstanceState()
を使用した状態の保存状況は、API レベルによって異なります。API 28 より前のすべての API レベルでは、onSaveInstanceState()
が onStop()
の前に呼び出されます。API レベルが 28 以降の場合、呼び出し順序は逆になります。
フラグメント CREATED とビュー DESTROYED
すべての終了アニメーションと遷移が終了し、フラグメントのビューがウィンドウからデタッチされると、フラグメントのビュー Lifecycle
は DESTROYED
状態に移行し、ON_DESTROY
イベントがオブザーバーに送信されます。次にこのフラグメントは、その onDestroyView()
コールバックを呼び出します。この時点で、フラグメントのビューはライフサイクルの最後に到達し、getViewLifecycleOwnerLiveData()
は null
値を返します。
この時点で、フラグメントのビューへのすべての参照が削除され、フラグメントのビューがガベージ コレクションの対象になります。
フラグメント DESTROYED
フラグメントが削除された場合、または FragmentManager
が破棄された場合は、フラグメントの Lifecycle
が DESTROYED
状態に移行し、ON_DESTROY
イベントがオブザーバーに送信されます。次にこのフラグメントは、その onDestroy()
コールバックを呼び出します。この時点で、フラグメントはライフサイクルの最後に到達しています。
参考情報
フラグメントのライフサイクルの詳細については、以下の参考情報をご覧ください。