Lifecycle 2.8.0以降でdropUnlessResumed
dropUnlessStarted
というAPIが追加されています。
以下のように画面遷移のコードを囲うことで、ナビゲーションの連打・同時押しを防ぐことができます。
Button(
onClick = dropUnlessResumed { navController.navigate(SCREEN) }
) {
// ...
}
注意点
dropUnlessResumed
の返り値は () -> Unit
です。従って次のように書くことはできません。
@Composable
fun ScreenA() {
Component(
navigateToB = dropUnlessResumed { /* ... */ }
)
}
@Composable
fun Component(
navigateToB: (userId: String) -> Unit
) {
// ...
}
内部実装
単純にライフサイクルをチェックしているだけのようです。
@Composable
fun dropUnlessResumed(
lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
block: () -> Unit,
): () -> Unit = dropUnlessStateIsAtLeast(State.RESUMED, lifecycleOwner, block)
@Composable
private fun dropUnlessStateIsAtLeast(
state: State,
lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
block: () -> Unit,
): () -> Unit {
require(state != State.DESTROYED) { "..." }
return {
if (lifecycleOwner.lifecycle.currentState.isAtLeast(state)) {
block()
}
}
}