Compose 1.4.0迁移:forEachGesture转awaitEachGesture遇死循环问题
Compose 1.4.0中repeatingClickable从forEachGesture迁移到awaitEachGesture的正确方案
升级到Compose 1.4.0后,forEachGesture被标记为弃用,官方建议改用awaitEachGesture。你尝试迁移时出现死循环,核心问题是:
- 移除了原代码中的协程
launch逻辑,导致重复点击的循环与waitForUpOrCancellation()串行执行,且循环内无延迟,直接高频触发onClick; down.pressed是首次按下时的状态判断,没有实时更新机制,导致循环条件始终为true。
正确迁移后的代码
fun Modifier.repeatingClickable( interactionSource: InteractionSource, enabled: Boolean = true, maxDelayMillis: Long = 500, minDelayMillis: Long = 50, delayDecayFactor: Float = .20f, onClick: () -> Unit ): Modifier = composed { val currentClickListener by rememberUpdatedState(onClick) pointerInput(interactionSource, enabled) { awaitEachGesture { coroutineScope { awaitPointerEventScope { val down = awaitFirstDown(requireUnconsumed = false) val heldButtonJob = launch { var currentDelayMillis = maxDelayMillis while (enabled && down.pressed) { currentClickListener() delay(currentDelayMillis) val nextMillis = currentDelayMillis - (currentDelayMillis * delayDecayFactor) currentDelayMillis = nextMillis.toLong().coerceAtLeast(minDelayMillis) } } waitForUpOrCancellation() heldButtonJob.cancel() } } } } }
关键说明
awaitEachGesture与forEachGesture语义一致,都是循环处理连续的手势事件,替换后无需修改核心逻辑;- 保留
coroutineScope和launch:通过协程后台执行重复点击逻辑,同时主线程阻塞等待waitForUpOrCancellation()(手指抬起或手势取消),避免死循环; waitForUpOrCancellation()完成后立即取消后台协程,终止重复点击触发。
内容的提问来源于stack exchange,提问作者Clandes
相关产品推荐
相关产品推荐

