Open5

【Android】whenLifecycle / whenStarted / whenResumed

watabeewatabee

whenLifecycle は特定のライフサイクル状態になったら引数で指定したラムダが実行される。

@Composable
private fun whenLifecycle(
    state: State,
    lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
    onState: () -> Unit,
): () -> Unit {
    require(state != State.DESTROYED) {
        "Target state is not allowed to be `Lifecycle.State.DESTROYED` because Compose disposes " +
            "of the composition before `Lifecycle.Event.ON_DESTROY` observers are invoked."
    }

    return {
        if (lifecycleOwner.lifecycle.currentState == state) {
            onState()
        }
    }
}
watabeewatabee

whenLifecycle はプライベートメソッドになっており、パブリックなメソッドとして whenStartedwhenResumed がある。

@Composable
fun whenStarted(
    lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
    onStarted: () -> Unit,
): () -> Unit = whenLifecycle(State.STARTED, lifecycleOwner, onStarted)
@Composable
fun whenResumed(
    lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
    onResumed: () -> Unit,
): () -> Unit = whenLifecycle(State.RESUMED, lifecycleOwner, onResumed)
watabeewatabee

用途としてはコメントに記載してあるようにクリック時や画面遷移時に Start, Resume 状態を保証したい場合に使える。

MyComposable(
  onClick = whenStarted {
    // Do something on clicks, if and only if, the lifecycle state is RESUMED
  }
)
composable(...) { entry: NavBackStackEntry ->
  ...,
  Screen1(
    navigateToScreen = whenResumed {
      navController.navigate("screen2")
  },
watabeewatabee

先日 Navigation Compose で画面を戻る際に二重タップされて画面遷移がおかしくなる不具合があったため、まさにこれが使えそう。

あとは例えばタップを契機にして Fragment を表示する場合にこの対応を入れておけば、onSaveInstanceState が呼び出された後に Fragment を呼び出してクラッシュしてしまうといったことも防げそう。