Jetpack Compose の Lifecycle   Android Jetpack の一部.

ライフサイクル対応コンポーネントは、ホスト アクティビティのライフサイクル ステータスの変化に対応してアクションを実行します。 androidx.lifecycle.compose アーティファクトには、画面から離れたときやアプリがバックグラウンドに移行したときにリソースを自動的にクリーンアップする専用の API が用意されています。

主な API は次のとおりです。

これらの統合により、Compose の階層内でライフサイクルを管理するための便利なフックが提供されます。このドキュメントでは、アプリでこれらの API を使用する方法について説明します。

フローを使ってライフサイクルの状態を収集する

Lifecycle は、現在の Lifecycle.State を Kotlin の StateFlow として提供する currentStateFlow プロパティを公開しています。この FlowState として収集できます。これにより、アプリはコンポーズ中にライフサイクルの変更を読み取ることができます。

val lifecycleOwner = LocalLifecycleOwner.current
val stateFlow = lifecycleOwner.lifecycle.currentStateFlow

val currentLifecycleState by stateFlow.collectAsState()

上記の例には lifecycle-common モジュールを使ってアクセスできます。lifecycle-runtime-compose モジュールには currentStateAsState() メソッドがありますが、このメソッドを使用すると、現在の Lifecycle の状態を 1 行で簡単に読み取ることができます。次の例はこの方法を示したものです。

val lifecycleOwner = LocalLifecycleOwner.current
val currentLifecycleState = lifecycleOwner.lifecycle.currentStateAsState()

ライフサイクル イベントでコードを実行する

`DefaultLifecycleObserver` を実装する別のクラスを作成してライフサイクルに手動で追加する代わりに、特定のエフェクトを使用してライフサイクル ロジックをインラインで宣言できます。DefaultLifecycleObserverLifecycleEffects を使用すると、特定の Lifecycle.Event がコンポーズ内で直接発生したときにブロックを実行できます。

LifecycleEventEffect

LifecycleEventEffect を使用すると、特定のイベントが発生したときにコードブロックを実行できます。 これは、成功も即時の結果も必要としないロギングや分析などのワンショット イベントに最適です。

@Composable
fun AnalyticsTracker(screenName: String) {
    // Log an event when the app receives ON_RESUME (e.g. comes to foreground)
    LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
        Analytics.logView(screenName)
    }
}

LifecycleStartEffect

アプリの起動時 (表示時)に実行し、アプリの停止時(バックグラウンド時)にクリーンアップする必要があるペアの開始/停止オペレーションには、 LifecycleStartEffect を使用します。

他の Compose エフェクト(LaunchedEffect など)と同様に、LifecycleStartEffect はキーを受け入れます。キーが変更されると、ブロックの再実行がトリガーされます。

Lifecycle.Event.ON_STOP イベントが発生したときや、エフェクトがコンポーズを終了するときに、onStopOrDispose ブロックが実行され、開始ブロックに含まれていた処理がクリーンアップされます。

@Composable
fun LocationMonitor(locationManager: LocationManager) {
    // Starts monitoring when ON_START is dispatched
    // Stops monitoring when ON_STOP is dispatched
    //   (or the composable leaves the screen)
    LifecycleStartEffect(locationManager) {
        val listener = LocationListener { location ->
            /* update UI */
        }
        locationManager.requestLocationUpdates(listener)
        // The cleanup block automatically runs on ON_STOP or on disposal
        onStopOrDispose {
            locationManager.removeUpdates(listener)
        }
    }
}

他の種類の副作用については、 Compose における副作用をご覧ください。

LifecycleResumeEffect

LifecycleResumeEffectLifecycleStartEffect と同じように動作しますが、Lifecycle.Event.ON_RESUME イベントに結び付けられています。また、ON_PAUSE がディスパッチされたときや、コンポーズ可能な関数が画面から離れたときにクリーンアップを実行する onPauseOrDispose ブロックも提供します。

この API は、ユーザーがアプリを操作している場合にのみアクティブにする必要があるリソース(カメラやアニメーションなど)に便利です。

@Composable
fun CameraPreview(cameraController: CameraController) {
    LifecycleResumeEffect(cameraController) {
        cameraController.startPreview()

        onPauseOrDispose {
            cameraController.stopPreview()
        }
    }
}

LifecycleOwner にアクセスする

Compose では、 LifecycleOwnerCompositionLocal という名前の LocalLifecycleOwner を介して暗黙的に使用できます。デフォルトでは、コンポーズ階層のルートホストがこのオーナーを提供します。

val lifecycleOwner = LocalLifecycleOwner.current

多くのアプリでは、このデフォルトのオーナーを検査するか、ライフサイクル対応エフェクトに渡すだけで十分です。ただし、カスタム ナビゲーションや複雑なレイアウトの場合は、独自の LifecycleOwner を作成して、ライフサイクル状態を UI の特定のセクションにスコープ設定することをおすすめします。たとえば、ナビゲーション ライブラリ(Navigation 3 など)は、各 画面に独自のライフサイクルを提供するために、これを自動的に行います。

カスタムの LifecycleOwner を作成する

rememberLifecycleOwner() API を使用すると、カスタムの LifecycleOwner を作成して記憶できます。これは、HorizontalPager などのコンポーネントで特に便利です。このコンポーネントでは、表示されている固定ページのみを RESUMED にし、隣接する画面外のページには STARTEDmaxState を設定します。

val pagerState = rememberPagerState(pageCount = { 10 })

HorizontalPager(state = pagerState) { pageNum ->
    val pageLifecycleOwner = rememberLifecycleOwner(
        maxState = if (pagerState.settledPage == pageNum) {
            Lifecycle.State.RESUMED
        } else {
            Lifecycle.State.STARTED
        }
    )

    CompositionLocalProvider(LocalLifecycleOwner provides pageLifecycleOwner) {
        // Your pages here. Their lifecycle-aware components respect the
        // custom maxState defined above.
    }
}

CompositionLocal の詳細については、CompositionLocal でローカルにスコープ設定されたデータをご覧ください。

ライフサイクル対応コンポーネントに関するおすすめの方法

  • UI コントローラはできる限りシンプルにします。データの取得には UI コントローラ自体でなく ViewModel を使い、StateFlow オブジェクトを監視して変更を UI に反映させます。
  • データの変更時に UI コントローラが UI を更新するデータ主導型の UI を作成するか、ユーザー アクションを ViewModelに通知するようにします。
  • データのロジックを ViewModel クラスに実装します。 ViewModel は、UI コントローラとその他のアプリ間のコネクタとして機能する必要があります。ただし、ネットワークなどからのデータの取得は ViewModel の責任ではありません。代わりに、 ViewModel で適切なコンポーネントを呼び出し、そのコンポーネントを使ってデータを取得して を UI コントローラに返します。
  • Kotlin コルーチンを使用して、 長時間実行されるタスクと非同期に実行できるその他のオペレーションを管理します。
  • 開始/停止ロジックは、実際に必要なコンポーズ可能な関数内に保持します。これにより、特定の UI 要素が画面から削除された場合(ナビゲーション グラフ内や表示が条件付きの場合など)、ロジックが自動的に削除されます。
  • データには collectAsStateWithLifecycle を使用します。ライフサイクル イベントに基づいて Flow コレクションを手動で開始または停止しないでください。代わりに、collectAsStateWithLifecycle を使用して、ストリームを UI 状態に効率的に変換します。 アプリがバックグラウンドにあるときに Flow が一時停止されるため、バッテリーとリソースを節約できます。

Flow の詳細については、その他のサポートされている状態タイプをご覧ください。

ライフサイクル対応コンポーネントのユースケース

ライフサイクル対応コンポーネントを使用すると、さまざまなケースにおいてライフサイクルを極めて簡単に管理できるようになります。以下に例を示します。

  • 大まかな現在地情報と詳細な現在地情報の切り替え。LifecycleStartEffect を使用すると、アプリが表示されている間(ON_START)は詳細な現在地情報を有効にし、アプリがバックグラウンドにあるとき(ON_STOP)はリスナーを自動的にクリーンアップするか、大まかな現在地情報に切り替えることができます。
  • 動画のバッファリングの停止と開始。LifecycleResumeEffect を使用すると、アプリが完全にフォアグラウンドでインタラクティブになるまで(ON_RESUME)実際の動画再生を遅延させ、アプリがバックグラウンドに移行したとき(ON_PAUSE)に再生を一時停止してリソースを解放できます。
  • ネットワーク ストリーミングの開始と停止。collectAsStateWithLifecycle を使用して、連続するデータ ストリーム(ネットワーク ソケットからの Kotlin フローなど)を監視します。これにより、アプリがフォアグラウンドにあるときにリアルタイム更新が行われ、アプリがバックグラウンドに移行するとコレクションが自動的にキャンセルされます。
  • 負荷の高いタスクの一時停止と再開。LifecycleResumeEffect を使用すると、アプリがバックグラウンドにあるときに負荷の高いビジュアル更新を一時停止し、アプリがフォアグラウンドになった後に再開できます。

ON_STOP イベントを安全に処理する

Compose は、ON_STOP イベントを安全に処理するように設計されています。

  • 状態は安全です。 アプリがバックグラウンドにある場合でも、MutableState をいつでも更新できます(uiState.value = ... など)。 Compose は、アプリが表示されるまで変更のレンダリングを待機します。
  • 自動クリーンアップ: LifecycleStartEffect などのエフェクトを使用すると、ライフサイクルが STOPPED に移行したときに、クリーンアップ ブロック(onStopOrDispose)が正確に実行されます。これにより、アプリがバックグラウンドにあるときに、カメラや位置情報などの負荷の高いリソースを保持することを防ぐことができます。

MutableState の詳細については、状態と Jetpack Compose をご覧ください。

参考情報

ライフサイクル対応コンポーネントによるライフサイクルへの対応について詳しくは、以下の参考情報をご覧ください。

Views コンテンツ