实施 debounce click suffer Modifier.composed 的不必要使用?

Implement debounce click suffer Unnecessary use of Modifier.composed?

我正在尝试创建一个 debounce 可点击的 Compose 修改器作为下面的代码片段。

inline fun Modifier.debounceClickable(
    debounceInterval: Long = 400,
    crossinline onClick: () -> Unit,
): Modifier = composed {
    var lastClickTime = 0L
    clickable() {
        val currentTime = System.currentTimeMillis()
        if ((currentTime - lastClickTime) < debounceInterval) return@clickable
        lastClickTime = currentTime
        onClick()
    }
}

不确定为什么 IDE 警告 不必要地使用 Modifier.composed

顺便说一句,这个去抖动工具有没有潜在的危险或泄漏?

您只需使用 composed 即可拨打 @Composable 个电话。

请注意,在 composed 中,您应该只使用带有状态注释的可组合项,例如使用 remember 保存一些状态,而不是可组合视图。可以找到更多详细信息 .

所以从技术上讲,要消除警告,您可以将代码简化为:

inline fun Modifier.debounceClickable(
    debounceInterval: Long = 400,
    crossinline onClick: () -> Unit,
): Modifier {
    var lastClickTime = 0L
    return clickable() {
        val currentTime = System.currentTimeMillis()
        if ((currentTime - lastClickTime) < debounceInterval) return@clickable
        lastClickTime = currentTime
        onClick()
    }
}

它的工作原理与您当前的代码相同。

问题是您将数据存储在 lastClickTime 中,并且您的代码会在第一次重组发生后立即重置。仅当您不通过操作更改 UI 时,它才可能正常工作。

您可以使用以下内核进行测试:

var flag by remember { mutableStateOf(false) }
Text("clickable $flag", Modifier.debounceClickable { flag = !flag } )

这就是为什么您实际上需要 composed 来使用 remembermutableStateOf 存储此值,就像在任何其他视图中一样:

inline fun Modifier.debounceClickable(
    debounceInterval: Long = 400,
    crossinline onClick: () -> Unit,
): Modifier = composed {
    var lastClickTime by remember { mutableStateOf(0L) }
    clickable() {
        val currentTime = System.currentTimeMillis()
        if ((currentTime - lastClickTime) < debounceInterval) return@clickable
        lastClickTime = currentTime
        onClick()
    }
}

我建议您查看 Compose documentation, including this youtube video 中的状态,它解释了基本原理。