发布于 2019-07-29 19:22:39
我已经创建了一个带有三个去反弹运算符的gist,灵感来自Patrick中的this elegant solution,我在其中添加了两个类似的案例:throttleFirst
和throttleLatest
。这两个都与他们的RxJava类似物(throttleFirst,throttleLatest)非常相似。
throttleLatest
的工作方式类似于debounce
,但它按时间间隔操作,并返回每个时间间隔的最新数据,这允许您在需要时获取和处理中间数据。
fun <T> throttleLatest(
intervalMs: Long = 300L,
coroutineScope: CoroutineScope,
destinationFunction: (T) -> Unit
): (T) -> Unit {
var throttleJob: Job? = null
var latestParam: T
return { param: T ->
latestParam = param
if (throttleJob?.isCompleted != false) {
throttleJob = coroutineScope.launch {
delay(intervalMs)
latestParam.let(destinationFunction)
}
}
}
}
当您需要立即处理第一个调用,然后跳过后续调用一段时间以避免不受欢迎的行为时(例如,避免在安卓上启动两个相同的活动),throttleFirst
非常有用。
fun <T> throttleFirst(
skipMs: Long = 300L,
coroutineScope: CoroutineScope,
destinationFunction: (T) -> Unit
): (T) -> Unit {
var throttleJob: Job? = null
return { param: T ->
if (throttleJob?.isCompleted != false) {
throttleJob = coroutineScope.launch {
destinationFunction(param)
delay(skipMs)
}
}
}
}
debounce
有助于检测一段时间内未提交新数据时的状态,从而有效地允许您在输入完成时处理数据。
fun <T> debounce(
waitMs: Long = 300L,
coroutineScope: CoroutineScope,
destinationFunction: (T) -> Unit
): (T) -> Unit {
var debounceJob: Job? = null
return { param: T ->
debounceJob?.cancel()
debounceJob = coroutineScope.launch {
delay(waitMs)
destinationFunction(param)
}
}
}
所有这些运算符都可以按如下方式使用:
val onEmailChange: (String) -> Unit = throttleLatest(
300L,
viewLifecycleOwner.lifecycleScope,
viewModel::onEmailChanged
)
emailView.onTextChanged(onEmailChange)
发布于 2020-10-25 07:37:10
对于从ViewModel
内部执行的一种简单方法,您可以在viewModelScope
中启动一个作业,跟踪该作业,如果在作业完成之前出现新值,则取消该作业:
private var searchJob: Job? = null
fun searchDebounced(searchText: String) {
searchJob?.cancel()
searchJob = viewModelScope.launch {
delay(500)
search(searchText)
}
}
发布于 2020-02-25 11:05:33
我使用来自Kotlin Coroutines的callbackFlow和debounce来实现去抖动。例如,要实现按钮单击事件的去抖动,请执行以下操作:
在Button
上创建扩展方法以生成callbackFlow
fun Button.onClicked() = callbackFlow<Unit> {
setOnClickListener { offer(Unit) }
awaitClose { setOnClickListener(null) }
}
订阅生命周期感知活动或片段中的事件。下面的代码片段每隔250ms揭开点击事件的面纱:
buttonFoo
.onClicked()
.debounce(250)
.onEach { doSomethingRadical() }
.launchIn(lifecycleScope)
https://stackoverflow.com/questions/50858684
复制相似问题