3
8

More than 1 year has passed since last update.

【Android】LifecycleOwner として Fragment 自身ではなく viewLifecycleOwner を使うべき場合

Posted at

Fragment クラスは LifecycleOwner インターフェイスを実装しています。
しかし LifecycleOwner オブジェクトとして、Fragment オブジェクト自身ではなく、
Fragment.viewLifecycleOwner プロパティが返すオブジェクトを使うべき場合があります。

本稿では、まず前提となる ライフサイクル、Lifecycle クラス、LifecycleOwner インターフェイス について簡単に説明してから、その本題について説明します。

ライフサイクル

アクティビティやフラグメントにはライフサイクルがあります。

アクティビティのライフサイクル フラグメントのライフサイクル

画像は以下より。

Lifecycle クラス

Lifecycle クラスはアクティビティやフラグメントのライフサイクルを表します。

Lifecycle.addObserver(LifecycleObserver) 関数を用いることで、以下のライフサイクルイベントを監視することができます。

ライフサイクルイベント 発行タイミング
ON_CREATE onCreate の後
ON_START onStart の後
ON_RESUME onResume の後
ON_PAUSE onPause の前
ON_STOP onStop の前
ON_DESTORY onDestory の前

LifecycleOwner インターフェイス

Lifecycle オブジェクトは LifecycleOwner インターフェイスlifecycle プロパティから取得できます。
Activity クラスや Fragment クラスは LifecycleOwner インターフェイスを実装しています。

ライフサイクルイベントを監視する主要な API

次のような API は Lifecycle オブジェクトが発行するライフサイクルイベントを監視して動作の変更を行います。

API 説明
Lifecycle.coroutineScope プロパティ
LifecycleOwner.lifecycleScope プロパティ1
ON_DESTORY イベントでキャンセルされる CoroutineScope オブジェクトを返す。
LiveData.observe(LifecycleOwner, Observer<Object>) 関数 LiveData オブジェクトの監視を開始する。ON_DESTORY イベントで解除される。

他にも色々あるはずですが、
不要になったら自動で解除するようなものは基本的に
ON_DESTROY イベントで解除すると考えられます。

フラグメントのライフサイクルの問題

フラグメントのライフサイクルを再度確認してみましょう。

フラグメントのライフサイクル(再掲)

フラグメントでは onDestory に行かず onCreateView に戻る流れがあります。

つまり、onCreateViewonActivityCreated などのライフサイクル関数で開始した処理
ON_DESTROY イベントで解除しようとしていると、
解除していないのに再度開始してしまうことが起こります。

例えば onCreateViewLiveData.observe 関数を呼び出した場合だと、値が変更された時の処理が多重に呼ばれることになります。

Fragment.viewLifecycleOwner プロパティで解決

この問題を解決するのが Fragment.viewLifecycleOwner プロパティです。

このプロパティは LifecycleOwner オブジェクトを返しますが、
それは Fragment クラスが実装しているものとは異なります。

この LifecycleOwner オブジェクトの lifecycle プロパティが返す Lifecycle オブジェクトは、ON_CREATE イベントと ON_DESTROY イベントの発行タイミングが次のようになります。(他の4イベントは同じです。)

ライフサイクルイベント 発行タイミング
ON_CREATE onViewStateRestored の後(onCreateView より後)
ON_DESTROY onDestroyView の前

そのため onCreateView から onViewStateRestored までの間に開始した処理を
onDestroyView で解除することができ、
すなわち onDestory が呼ばれずに再度 onCreateView が呼ばれても、多重に実行されるということがないようにできます。

フラグメントのライフサイクル(詳細版)

画像は下記より。Android 公式の図より細かくなっています。

まとめ

Fragment オブジェクト自身を LifecycleOwner として使うと問題がある場合があります。
代わりに Fragment.viewLifecycleOwner プロパティが返す LifecycleOwner オブジェクトを使用することを検討しましょう。

Fragment.viewLifecycleOwner プロパティを使うべきなのは、
onCreateView もしくはそれ以降のライフサイクル関数で開始した処理を ON_DESTROY イベントで解除する場合です。

また、LifecycleOwner拡張関数拡張プロパティを、そうと意識せず、viewLifecycleOwner プロパティから使うべき場合に Fragment オブジェクトから直接使ってしまわないようにも注意しましょう。

参考資料

/以上

  1. LifecycleOwner.lifecycleScope プロパティは内部で Lifecycle.coroutineScope プロパティを呼んでいる。

3
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
8