I'm trying to create a debounce clickable Compose Modifier as code snippet below.
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()
}
}
Not sure why the IDE warned Unnecessary use of Modifier.composed ?
BTW, is this debounce implement got any potential danger or leak ?
You only need to use composed
to make @Composable
calls.
Note, that inside composed
you should only use state annotated composables, like to save some state using remember
, but not the composable views. More details can be found here.
So technically, to get rid of the warning, you could've simplified your code to this:
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()
}
}
And it would work the same, as your current code.
The problem is that you store data in lastClickTime
, and with your code it's gonna be reset as soon as the first recomposition happens. It may work fine only if you don't change UI with the action.
You can test it with the following core:
var flag by remember { mutableStateOf(false) }
Text("clickable $flag", Modifier.debounceClickable { flag = !flag } )
That's why you actually need composed
to store this value using remember
and mutableStateOf
, just like in any other view:
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()
}
}
I suggest you check out with state in Compose documentation, including this youtube video which explains the basic principles.