Pablo
05/18/2021, 3:38 PMfun <T> debounce(
delayMillis: Long = 300L,
scope: CoroutineScope,
action: (T) -> Unit
): (T) -> Unit {
var debounceJob: Job? = null
return { param: T ->
if (debounceJob == null) {
debounceJob = scope.launch {
action(param)
delay(delayMillis)
debounceJob = null
}
}
}
}
Where I can do
fun setDebounceListener(view: Button, onClickListener: View.OnClickListener) {
val clickWithDebounce: (view: View) -> Unit =
debounce(scope = MainScope()) {
onClickListener.onClick(it)
}
view.setOnClickListener(clickWithDebounce)
}
Does it make sense to use debounce here? It's just to avoid double click on a Buttonlouiscad
05/18/2021, 4:20 PMawaitOneClick()
in the flow { … }
builder.Pablo
05/19/2021, 7:35 AMlouiscad
05/19/2021, 7:36 AMPablo
05/19/2021, 7:40 AMlouiscad
05/19/2021, 7:40 AMxxxLatest
operators if called from a flow operatorPablo
05/19/2021, 7:40 AMlouiscad
05/19/2021, 7:42 AMawaitOneClick()
again until your app wants to allow clicks againsuspend handleStuff() {
while (true) {
btn.awaitOneClick()
doStuff()
}
}
Pablo
05/19/2021, 7:44 AMlouiscad
05/19/2021, 7:44 AMdoStuff()
is a suspending function)Pablo
05/19/2021, 7:44 AMfun View.clicks(): Flow<Unit> = callbackFlow {
setOnClickListener {
offer(Unit)
}
awaitClose { setOnClickListener(null) }
}
louiscad
05/19/2021, 7:45 AMPablo
05/19/2021, 7:45 AMbutton.clicks().debounce(1000).onEach { println("clicked") }.launchIn(GlobalScope)
louiscad
05/19/2021, 7:46 AMFlow
is the following:
fun View.clicks(): Flow<Unit> = flow {
while (true) {
awaitOneClick()
emit(Unit)
}
}
emit
is suspending (which is when the lambda of collect
is executing)Pablo
05/19/2021, 7:48 AMlouiscad
05/19/2021, 7:49 AMPablo
05/19/2021, 7:49 AMlouiscad
05/19/2021, 7:49 AMawaitOneClick()
Pablo
05/19/2021, 7:49 AMlouiscad
05/19/2021, 7:50 AMPablo
05/19/2021, 7:50 AMlouiscad
05/19/2021, 7:51 AMPablo
05/19/2021, 7:54 AMlouiscad
05/19/2021, 7:56 AMPablo
05/19/2021, 7:58 AMlouiscad
05/19/2021, 7:59 AMPablo
05/19/2021, 8:01 AMlouiscad
05/19/2021, 8:01 AMPablo
05/19/2021, 8:02 AMscope.launch {
singleClick().onEach {
itemClicked.invoke(position)
}.launchIn(this)
}
louiscad
05/19/2021, 8:28 AMcollect
instead, yup. Also, having a flow that actually gives only one value ever is weird, name-wise, and use-wise, just using awaitOneClick()
would make more sense here.Pablo
05/19/2021, 8:30 AMlouiscad
05/19/2021, 8:46 AMPablo
05/19/2021, 8:47 AMfun View.clicks(): Flow<Unit> = flow {
while (true) {
awaitOneClick()
emit(Unit)
}
}
louiscad
05/19/2021, 8:47 AMPablo
05/19/2021, 8:47 AMlouiscad
05/19/2021, 8:50 AMPablo
05/19/2021, 8:52 AMlouiscad
05/19/2021, 8:56 AMdelay(timeMillis = 700)
or alike after doing it before calling awaitOneClick()
againPablo
05/19/2021, 8:57 AMlouiscad
05/19/2021, 8:58 AMPablo
05/19/2021, 8:58 AMlouiscad
05/19/2021, 9:00 AMView
that takes a CoroutineScope
Pablo
05/19/2021, 9:01 AMlouiscad
05/19/2021, 9:01 AMawaitOneClick()
. suspendCancellable
is an implementation detail of awaitOneClick
Pablo
05/19/2021, 9:03 AMsuspend fun View.awaitOneClick(
disableAfterClick: Boolean = true,
hideAfterClick: Boolean = false,
onClick: (View) -> Unit,
) = try {
if (disableAfterClick) isEnabled = true
if (hideAfterClick) isVisible = true
suspendCancellableCoroutine<Unit> { continuation ->
setOnClickListener {
onClick.invoke(it)
continuation.resume(Unit)
}
}
} finally {
setOnClickListener(null)
if (disableAfterClick) isEnabled = false
if (hideAfterClick) isVisible = false
}
louiscad
05/19/2021, 9:03 AMPablo
05/19/2021, 9:04 AMawaitOneClick { //do something }
louiscad
05/19/2021, 9:04 AMawaitOneClick()
(kidding about the TM, but you can find a clearer name to the function that'd use awaitOneClick()
)Pablo
05/19/2021, 9:06 AMscope.launch{
while(true){
delay(700)
awaitOnClick{
onClick.invoke(position)
}
}
louiscad
05/19/2021, 9:09 AMawaitOneClick()
?
Just put if after calling awaitOneClick()
.delay
should be after that code, not before.Pablo
05/19/2021, 9:10 AMYou see the code you want to pass in the non existing lambda ofI add it in your code when I said "I have this from now"?awaitOneClick()
louiscad
05/19/2021, 9:13 AMlaunchLoop
is launch
on a scope + while (isActive)
Pablo
05/19/2021, 9:21 AMfun View.handleSingleClick(scope: CoroutineScope, block: () -> Unit) {
scope.launch{
while(true){
awaitOneClick()
block()
delay(700)
}
}
}
louiscad
05/19/2021, 9:26 AMPablo
05/19/2021, 9:26 AMlouiscad
05/19/2021, 9:27 AM