Slide 1

Slide 1 text

Compose のライフサイクル対応 を支援する LifecycleEventEffect の紹介 YUMEMI.grow Mobile #6 一瀬喜弘(@mikanIchinose)

Slide 2

Slide 2 text

自己紹介 object Mikan { val name = " 一瀬喜弘" val company = "karabiner.tech" val hobby = listOf( " 漫画", " アニメ", " ゲーム", " 折り紙", "OSS 開発・コントリビュート", ) }

Slide 3

Slide 3 text

目次 LifecycleEventEffect なる副作用が入ることを知る 追加されたAPI の紹介 Compose の中でLifecycle-aware な何かを扱う場合のTips まとめ

Slide 4

Slide 4 text

LifecycleEventEffect なる副作用が入ることを知る

Slide 5

Slide 5 text

alpha リリースに入った!!

Slide 6

Slide 6 text

これまでのライフサイクル対応 DisposbleEffect とLifecycleEventObserver を利用する val lifecycle = LocalLifecycleOwner.current.lifecycle DisposableEffect(lifecycle) { val lifecycleObserver = LifecycleEventObserver { _, event -> if (event == Lifecycle.Event.ON_RESUME) { // do something } } lifecycle.addObserver(lifecycleObserver) onDispose { lifecycle.removeObserver(lifecycleObserver) } }

Slide 7

Slide 7 text

LifecycleEventEffect 1 つのライフサイクルイベントにたいして処理をフックできる @Composable fun LifecycleEventEffect( event: Lifecycle.Event, lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current, onEvent: () -> Unit )

Slide 8

Slide 8 text

LifecycleEventEffect 使い方 LifecycleEventEffect(Lifecycle.Event.ON_START) { // do something onStart } // イベントトラッキング LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { logger.trackScreenView(screen_name) } // データ更新 // 後述するLifecycle-aware なViewModel を紐付ける実装のほうがオススメ LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { viewModel.fetchData() }

Slide 9

Slide 9 text

LifecycleStartEffect ON_START, ON_STOP 時に処理をフックする @Composable fun LifecycleStartEffect( vararg keys: Any?, lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current, effects: LifecycleStartStopEffectScope.() -> LifecycleStopOrDisposeEffectResult )

Slide 10

Slide 10 text

LifecycleStartEffect 使い方 onStopOrDispose :onStop とonDispose のときに処理を実行する LifecycleStartEffect { // ON_START で実行したい処理 onStopOrDispose { // ON_STOP で実行したい処理 } } ` `

Slide 11

Slide 11 text

LifecycleStartEffect 使い方 @Composable fun Counter() { var count by remember { mutableStateOf(0) } LaunchedEffect(count) { delay(1000) count++ } LifecycleStartEffect(count) { Log.d("Counter", "onStart") onStopOrDispose { Log.d("Counter", "onStop or onDispose") } } Text(text = "$count") }

Slide 12

Slide 12 text

LifecycleResumeEffect ON_RESUME, ON_PAUSE 時に処理をフックする @Composable fun LifecycleResumeEffect( vararg keys: Any?, lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current, effects: LifecycleResumePauseEffectScope.() -> LifecyclePauseOrDisposeEffectResult )

Slide 13

Slide 13 text

Lifecycle.currentStateFlow Lifecycle.currentStateAsState Lifecycle.eventFlow open val currentStateFlow: StateFlow @Composable fun Lifecycle.currentStateAsState(): State // lifecycle.currentStateFlow.collectAsState() のショートハンド val Lifecycle.eventFlow: Flow

Slide 14

Slide 14 text

Tips: Lifecycle-aware な ViewModel を Compose に紐付 ける ライフサイクルを紐付けるだけで関数呼び出しを書かなくてよいのでタイミングを間違えることがない class MainViewModel : ViewModel(), DefaultLifecycleObserver { override fun onResume(owner: LifecycleOwner) { // fetch data // track event // ... } } val lifecycle = LocalLifecycleOwner.current.lifecycle DisposableEffect(lifecycle) { lifecycle.addObserver(viewModel) onDispose { lifecycle.removeObserver(viewModel) } }

Slide 15

Slide 15 text

Tips: Lifecycle-aware な ViewModel を Compose に紐付 ける class MainViewModel : ViewModel(), DefaultLifecycleObserver { override fun onResume(owner: LifecycleOwner) { // fetch data // track event // ... } } @Composable fun LifecycleObserver.observeLifecycleEvents(lifecycle: Lifecycle = LocalLifecycleOwner.current.lifecycle) { DisposableEffect(lifecycle) { lifecycle.addObserver(this@observeLifecycleEvents) onDispose { lifecycle.removeObserver(this@observeLifecycleEvents) } } }

Slide 16

Slide 16 text

Tips: Lifecycle-aware な ViewModel を Compose に紐付 ける class MainViewModel : ViewModel(), DefaultLifecycleObserver { override fun onResume(owner: LifecycleOwner) { // fetch data // track event // ... } } @Composable fun LifecycleObserver.observeLifecycleEvents(lifecycle: Lifecycle = LocalLifecycleOwner.current.lifecycle) { DisposableEffect(lifecycle) { lifecycle.addObserver(this@observeLifecycleEvents) onDispose { lifecycle.removeObserver(this@observeLifecycleEvents) } } } @Composable fun GreetingScreen(viewModel: MainViewModel) { viewModel.observeLifecycleEvents() // ... }

Slide 17

Slide 17 text

まとめ Lifecycle.{Event, State} をcoroutine やcompose で利用するための拡張が入った Lifecycle を扱う系の副作用が3 つ入った 従来のDisposableEffect を使ったボイラープレートを減らせそう( な気がする) LifecycleResumeEffect 、LifecycleStartEffect の実用的な使い方ワカラン