如何使用 Kotlin 协程使 setOnClickListener 去抖动 1 秒? [英] How can I debounce a setOnClickListener for 1 second using Kotlin Coroutines?

查看:142
本文介绍了如何使用 Kotlin 协程使 setOnClickListener 去抖动 1 秒?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当用户快速点击按钮时,showDialog() 方法会在彼此的顶部显示多次,因此当您关闭它时,它后面还有另一个.我正在寻找一种方法来忽略第二次点击 1 秒而不使用处理程序或检查前一次点击的时间.

When user taps fast on the button the showDialog() method displays multiple times on top of each other, so when you dismiss it there is another one behind it. I am looking for a way to ignore the second tap for 1 second without using a handler or check the previous tap's time.

//Button that opens a dialog
button.setOnClickListener {
    showDialog()
}

我正在寻找使用 Kotlin 协程或 Kotlin 流程的解决方案以供将来实现.

I am looking for a solution using Kotlin coroutines or Kotlin flows for future implementations.

推荐答案

最好使用简单的Flag来代替延迟,因为这不是一个好的用户体验.

It's better to use a simple Flag for that instead of delay as it's not a good user experience.

但是如果你想使用协程,你可以简单地使用 Kotlin Coroutine's Flow 应用此:

But if you want to use Coroutines, You can simply use Kotlin Coroutine's Flow to apply this:

首先,我为返回协程流程的点击事件创建了一个扩展函数.像这样:

First I created an Extension Function for the click event that returns a Coroutine's Flow. like this:

    fun View.clicks(): Flow<Unit> = callbackFlow {
    setOnClickListener {
        offer(Unit)
    }
    awaitClose { setOnClickListener(null) }
   } 

现在,您只需要像这样在 onCreate 中调用您的函数:

Now, All you need is Calling your Function in onCreate like this:

button.clicks().debounce(1000).onEach { println("clicked") }.launchIn(GlobalScope)

不要忘记在 build.gradle 文件中添加这些行:

Don't forget to add these lines in build.gradle file:

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3'

throttleFirst 运算符的 Flow 模拟尚未在 kotlin 协程中实现.但是,可以在扩展函数的帮助下实现:

The Flow analogue of throttleFirst operator is not implemented yet in kotlin coroutines. however, can be implemented with the help of Extension Functions:

@FlowPreview
@ExperimentalCoroutinesApi
fun <T> Flow<T>.throttleFirst(windowDuration: Long): Flow<T> = flow {
    var lastEmissionTime = 0L
    collect { upstream ->
        val currentTime = System.currentTimeMillis()
        val mayEmit = currentTime - lastEmissionTime > windowDuration
        if (mayEmit)
        {
            lastEmissionTime = currentTime
            emit(upstream)
        }
    }
}

变化如下:

binding.button.clicks().throttleFirst(1250)
        .onEach {
            //delay(100)
            showDialog()
        }.launchIn(GlobalScope)

此外,您可以使用 delay() 来处理此问题.根据您的需要轻松更改这些参数的值.

Also, you can use a delay() to handle this. Take it easy to change value of these parameters according to your needs.

这篇关于如何使用 Kotlin 协程使 setOnClickListener 去抖动 1 秒?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆