【Jetpack Compose】@Composable のライフサイクルをシンプルに使うには DisposableEffect

なんか、いろんな方法があるんだなあ、と。

👉 Lifecycle を Compose と統合する  |  App architecture  |  Android Developers

👉 ComposeでLifecycleを監視する(2023年9月バージョン) - Kenji Abe - Medium

いろいろ試しながらどこから使っていくのがいいか。を考える。

 

🤔 参考になるコードたち

調べてみると、

DisposableEffect を中心に考えるのがいいだろう、

と思える。


@Composable
fun LifecycleEffect(
  onCreate: () -> Unit = { },
  onStart: () -> Unit = { },
  onResume: () -> Unit = { },
  onPause: () -> Unit = { },
  onStop: () -> Unit = { },
  onDestroy: () -> Unit = { },
  onAny: () -> Unit = { }
) {
  val lifecycleOwner = LocalLifecycleOwner.current
  DisposableEffect(lifecycleOwner) {
    val observer = LifecycleEventObserver { _, event ->
      when (event) {
        Event.ON_CREATE -> onCreate()
        Event.ON_START -> onStart()
        Event.ON_RESUME -> onResume()
        Event.ON_PAUSE -> onPause()
        Event.ON_STOP -> onStop()
        Event.ON_DESTROY -> onDestroy()
        Event.ON_ANY -> onAny()
      }
    }
    lifecycleOwner.lifecycle.addObserver(observer)
    onDispose {
      lifecycleOwner.lifecycle.removeObserver(observer)
    }
  }
}

👉 PatchNote-Android/app/src/main/java/com/easyhz/patchnote/core/common/util/Lifecycle.kt at e24ff1d32831b54177348e079412c95b17e3f0f4 · easyhz/PatchNote-Android


@Composable
fun LifecycleEffect(
  lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
  onStart: (suspend () -> Unit)? = null,
  onPause: (suspend () -> Unit)? = null,
  onStop: (suspend () -> Unit)? = null
) {
  val scope = rememberCoroutineScope()
  val currentOnStart by rememberUpdatedState(onStart)
  val currentOnPause by rememberUpdatedState(onPause)
  val currentOnStop by rememberUpdatedState(onStop)

  DisposableEffect(lifecycleOwner) {
    val observer = LifecycleEventObserver { _, event ->
      scope.launch {
        when (event) {
          Lifecycle.Event.ON_START -> currentOnStart?.invoke()
          Lifecycle.Event.ON_PAUSE -> currentOnPause?.invoke()
          Lifecycle.Event.ON_STOP -> currentOnStop?.invoke()
          else -> {}
        }
      }
    }
    lifecycleOwner.lifecycle.addObserver(observer)

    onDispose {
      lifecycleOwner.lifecycle.removeObserver(observer)
    }
  }
}

👉 itunes/app/src/main/java/com/simgesengun/itunes/ui/launchedEffect/LifecycleEffect.kt at cc63faa4eb78f22a7e2e8b95c78e1ca30f4f11ad · simgesengun/itunes


@Immutable
enum class LifecycleEvent {
  OnStop
}

@Immutable
data class LifecycleHandler(
  val id: String,
  val event: LifecycleEvent,
  val onEvent: () -> Unit
)

@Composable
fun <R : Any> DestinationScope<R>.LifecycleEffect(
  event: LifecycleEvent,
  onEvent: () -> Unit
) {
  val id = remember { randomUUID() }
  DisposableEffect(this, id, event, onEvent) {
    navigator.update {
      it.copy(lifecycleHandlers = it.lifecycleHandlers + LifecycleHandler(
        id = id,
        event = event,
        onEvent = onEvent
      ))
    }
    onDispose {
      navigator.update { dest ->
        dest.copy(lifecycleHandlers = dest.lifecycleHandlers.filter { it.id != id })
      }
    }
  }
}

👉 showcase/common/src/iosMain/kotlin/dev/ahmedmourad/showcase/common/navigation/LifecycleHandler.kt at 83cc58c29acc2dc3bbcc4de0644e79e74826514e · AhmedMourad0/showcase

 

🤔 まとめ

まずは、ここらから記述していくのがいいのではないか。


@Composable
@NonRestartableComposable
fun DisposableLifecycleEffect(
  lifecycle: Lifecycle = LocalLifecycleOwner.current.lifecycle,
  onResume: () -> Unit,
  onPause: () -> Unit,
) {
  DisposableEffect(lifecycle) {
    val observer = LifecycleEventObserver { _, event ->
      when (event) {
        Lifecycle.Event.ON_RESUME -> onResume()
        Lifecycle.Event.ON_PAUSE -> onPause()
        else -> { }
      }
    }
    lifecycle.addObserver(observer)
    onDispose {
      lifecycle.removeObserver(observer)
    }
  }
}

👉 florisboard/app/src/main/kotlin/dev/patrickgold/florisboard/lib/compose/DisposableLifecycleEffect.kt at 35fd70ce6d2de05cf8be44fcd9a16b3b6d537453 · florisboard/florisboard

記述位置は Screen。

@NonRestartableComposable の意味を考えながら書く。

フォアグラウンド、バックグラウンドの切り分けにも使えるか。


関連ワード:  AndroidAndroidStudioGitHubIDEAKotlinおすすめ今さら聞けない初心者開発