【问题标题】:using coroutines for debouncing使用协程去抖动
【发布时间】:2020-08-29 19:02:20
【问题描述】:

有一个函数updateData(id:String, data: Any?),它将针对id 进行一些数据更新。 只想使用最后一个数据进行更新,如果此调用是针对相同的 id 太快一个接一个,则应丢弃前一个。

    private var _lastId = ""
    private var _lastCallJob: Job? = null
    private fun debouncingUpdateData(id: String, data: Any?) {

        if (_lastId == id) {
            _lastCallJob?.cancel()
            _lastCallJob = launch {
                delay(20)
                updateData(id, data)
            }
        } else {
            _lastId = id
            _lastCallJob = launch {
                delay(20)
                updateData(id, data)
            }
        }
    }

此实现将取消先前启动的_lastCallJob(未完成,很可能仍在等待 20 毫秒),前提是 id 相同。

但它不适用于像这样的情况 id = "1", id="2", id="3"

所以当这样调用时:

debouncingUpdateData("1", data)
debouncingUpdateData("2", data)
debouncingUpdateData("1", data)

由于_lastId 已更改为“2”,id==="1" 的第 3 次调用可能仍会发出(即使第 1 次仍在 20 milsec 延迟范围内)。

有更好的方法来使用协程进行去抖动吗?

【问题讨论】:

  • 您是否考虑过使用 Flow 及其内置的debounce 方法? kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/…
  • @fraggjkee,还没有,我想只要使用我们正在使用的任何版本的 kotlin。谢谢!承认不知道如何使用 Flow,对于这个多个“id”调用同一个函数的情况有什么帮助?
  • 作为一个快速的想法,您可以创建一个协程 Channel 并将 ID 更新发布到它。然后,您可以使用现有的asFlow 函数将此通道转换为 Flow。最后一步是将debounce 方法添加到此流中,并仅观察其排放并根据需要做出反应(加载数据等)。与我对 Rx 所做的非常相似 - Subject + debounce 但使用 Coroutines & Flow。
  • 听起来会有更多代码(会看看),也许只是用我的代码添加一个地图(id to job)。

标签: android kotlin-coroutines debouncing


【解决方案1】:

不确定是否有一些更简单的库函数,但似乎这可以消除多个id 案例

    private val idToJobMap = HashMap<String, Job>()
    private fun debouncingUpdateData(id: String, data: Any?) {

        idToJobMap[id]?.let { job ->
            job.cancel()
        }
        idToJobMap[id] = launch {
            delay(20)
            idToJobMap.remove(id)
            updateData(data)
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-05
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-19
    相关资源
    最近更新 更多