Android 点击防抖

作者: goodl | 来源:发表于2021-09-13 08:21 被阅读0次

Android 开发中点击事件的处理一般是网络请求、弹出提示、跳转界面。
如果用户快速连续点击两次,就会请求两次网络,或是弹出两次提示等。

为了避免这种情况的方法,需要做点击事件防抖,即在一定时间间隔内只响应第一次点击事件。

方式一

利用 view 的 clickable:

inline fun View.setThrottleListener(
    thresholdMillis: Long = 500L,
    crossinline block: () -> Unit
) {
    setOnClickListener {
        isClickable = false
        postDelayed({ isClickable = true }, thresholdMillis)
        block.invoke()
    }
}


// 使用方式
mBinding.btn.setThrottleListener {
    // 处理点击逻辑
}

方式二

在 view 的 tag 中记录最后一次点击时间,首先在 ids.xml 中添加:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="clickLastTimeKey" type="id" />
</resources>
var View.clickLastTime: Long
    get() = getTag(R.id.clickLastTimeKey) as? Long ?: 0
    set(value) = setTag(R.id.clickLastTimeKey, value)

fun View.setThrottleListener(thresholdMillis: Long = 500, block: () -> Unit) {
    setOnClickListener {
        val currentTime = SystemClock.elapsedRealtime()
        if (currentTime - clickLastTime >= thresholdMillis) {
            clickLastTime = currentTime
            block.invoke()
        }
    }
}


// 使用
mBinding.btn.setThrottleListener {
    // 处理点击逻辑
}

方式三

同样是记录最后一次点击时间,不过是使用 flow:

fun <T> Flow<T>.throttleFirst(thresholdMillis: Long): Flow<T> = flow {
    var lastTime = 0L
    collect { upstream ->
        val currentTime = SystemClock.elapsedRealtime()
        if (currentTime - lastTime >= thresholdMillis) {
            lastTime = currentTime
            emit(upstream)
        }
    }
}

@ExperimentalCoroutinesApi
fun View.clickFlow() = callbackFlow {
    setOnClickListener { trySend(Unit).onFailure { e -> e?.printStackTrace() } }
    awaitClose { setOnClickListener(null) }
}


// 使用
mBinding.btn.clickFlow().throttleFirst(500)
    .onEach {} // 处理点击逻辑
    .launchIn(lifecycleScope)

相关文章

网友评论

    本文标题:Android 点击防抖

    本文链接:https://www.haomeiwen.com/subject/vgetgltx.html