Flow 和 LiveData 之操作符:throttleFirst、 throttleLast 、throttleLatest、debounce

本文主要是介绍Flow 和 LiveData 之操作符:throttleFirst、 throttleLast 、throttleLatest、debounce,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Flow 和 LiveData 之操作符:throttleFirst、 throttleLast 、throttleLatest、debounce

文章目录

  • Flow 和 LiveData 之操作符:throttleFirst、 throttleLast 、throttleLatest、debounce
      • 前言
      • 一、Flow 之操作符扩展
        • 1. ThrottleFirst
        • 2. ThrottleLast
        • 3. ThrottleLatest
        • 4. Debounce (Flow自带)
      • 一、LiveData 之操作符扩展
        • 1. ThrottleFirst
        • 2. ThrottleLast
        • 3. ThrottleLatest
        • 4. Debounce
      • Tip

前言

因为使用kotlin 和协程后准备移除RxJava,其中大部分功能,可以使用Flow进行替代,但是出现了部分操作符功能缺少,所有进行改进。

这是一遍没有检验的文章,部分操作操作符只是按逻辑写的,没有测试。有几个只是按自己的需求写的,可能和RxJava的存在差异

一、Flow 之操作符扩展

1. ThrottleFirst
fun <T> Flow<T>.throttleFirst(duration: Long = 1000L) = this.throttleFirstImpl(duration)
fun <T> Flow<T>.throttleFirstImpl(periodMillis: Long): Flow<T> {return flow {var lastTime = 0Lcollect { value ->val currentTime = System.currentTimeMillis()if (currentTime - lastTime >= periodMillis) {lastTime = currentTimeemit(value)}}}
}
2. ThrottleLast
fun <T> Flow<T>.throttleLast(duration: Long = 1000L) = this.sample(duration)
3. ThrottleLatest
fun <T> Flow<T>.throttleLatest(duration: Long = 1000L) = this.throttleLatestImpl(duration)
internal fun <T> Flow<T>.throttleLatestImpl(periodMillis: Long): Flow<T> {return channelFlow {var lastValue: T?var timer: Timer? = nullonCompletion { timer?.cancel() }collect { value ->lastValue = valueif (timer == null) {timer = Timer()timer?.scheduleAtFixedRate(object : TimerTask() {override fun run() {val value = lastValuelastValue = nullif (value != null) {launch {send(value as T)}} else {timer?.cancel()timer = null}}},0,periodMillis)}}}
}
4. Debounce (Flow自带)
flow {emit(1)delay(90.milliseconds)emit(2)delay(90.milliseconds)emit(3)delay(1010.milliseconds)emit(4)delay(1010.milliseconds)emit(5)
}.debounce(1000.milliseconds)

一、LiveData 之操作符扩展

1. ThrottleFirst
/*** @Author stj* * @Date 2021/10/8-18:38* * @Email 375105540@qq.com* * 间隔固定时间内,取第一个的值*/
fun <T> LiveData<T>.throttleFirst(duration: Long = 1000L) = MediatorLiveData<T>().also { mld ->val source = thisval handler = Handler(Looper.getMainLooper())val isUpdate = AtomicBoolean(true)val runnable = Runnable {isUpdate.set(true)}mld.addSource(source) {if (isUpdate.compareAndSet(true,false)){mld.value = source.valuehandler.postDelayed(runnable, duration)}}
}
2. ThrottleLast
fun <T> LiveData<T>.throttleLast(duration: Long = 1000L) = MediatorLiveData<T>().also { mld ->val source = thisval handler = Handler(Looper.getMainLooper())val isUpdate = AtomicBoolean(true)val runnable = Runnable {if (isUpdate.compareAndSet(false,true)){mld.value = source.value}}mld.addSource(source) {if (isUpdate.compareAndSet(true,false)) {handler.postDelayed(runnable, duration)}}
}
3. ThrottleLatest
fun <T> LiveData<T>.throttleLatest(duration: Long = 1000L) = MediatorLiveData<T>().also { mld ->val source = thisval isFirst = AtomicBoolean(true)val handler =  HandlerCompat.createAsync(Looper.getMainLooper())val isUpdate = AtomicBoolean(true)val runnable = Runnable {if (isUpdate.compareAndSet(false,true)){mld.value = source.value}}mld.addSource(source) {if (isFirst.compareAndSet(true,false)){mld.value = source.value}if (isUpdate.compareAndSet(true,false)) {handler.postDelayed(runnable, duration)}}
}
4. Debounce
fun <T> LiveData<T>.debounce(duration: Long = 1000L) = MediatorLiveData<T>().also { mld ->val source = thisval handler = HandlerCompat.createAsync(Looper.getMainLooper())val runnable = Runnable {mld.value = source.value}mld.addSource(source) {handler.removeCallbacks(runnable)handler.postDelayed(runnable, duration)}
}

Tip

有几个没有测试过,因为需求需要了,所有改了几个,其他结果是按逻辑写的,可能会有问题

这篇关于Flow 和 LiveData 之操作符:throttleFirst、 throttleLast 、throttleLatest、debounce的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/679969

相关文章

C++操作符重载实例(独立函数)

C++操作符重载实例,我们把坐标值CVector的加法进行重载,计算c3=c1+c2时,也就是计算x3=x1+x2,y3=y1+y2,今天我们以独立函数的方式重载操作符+(加号),以下是C++代码: c1802.cpp源代码: D:\YcjWork\CppTour>vim c1802.cpp #include <iostream>using namespace std;/*** 以独立函数

GNSS CTS GNSS Start and Location Flow of Android15

目录 1. 本文概述2.CTS 测试3.Gnss Flow3.1 Gnss Start Flow3.2 Gnss Location Output Flow 1. 本文概述 本来是为了做Android 14 Gnss CTS 的相关环境的搭建和测试,然后在测试中遇到了一些问题,去寻找CTS源码(/cts/tests/tests/location/src/android/locat

C++可以被重载的操作符Overloadable operators

C++允许绝大多数操作符被重载,也就是重新定义操作符实现的功能,这样它们的行为可以被设计出来以适应所有的数据类型,包括类。 以下是C++可以被重载的操作符(Overloadable operators): //四则运算符+ - * / %+= -= *= /= %=//比较运算符> >= == != //赋值运算符= //位操作

c++/《重载操作符》

为什么要对运算符进行重载:         C++预定义中的运算符的操作对象只局限于基本的内置数据类型,但是对于我们自定义的类型(类)是没有办法操作的。但是大多时候我们需要对我们定义的类型进行类似的运算,这个时候就需要我们对这么运算符进行重新定义,赋予其新的功能,以满足自身的需求。 <返回类型说明符> operator <运算符符号>(<参数表>) { <函数体> }

【JavaScript】ES6之...延展操作符

… 操作符(也被叫做延展操作符 - spread operator)已经被 ES6 数组 支持。它允许传递数组或者类数组直接做为函数的参数而不用通过apply。      延展操作符一般用于属性的批量赋值上。    通过分析① test8(…args) ②test8(args) ③ test8.apply(null, args) 易看出区别

Understanding the GitHub Flow

这里看下Github的入门介绍    --链接 GitHub Flow is a lightweight, branch-based workflow that supports teams and projects where deployments are made regularly. This guide explains how and why GitHub Flow works

C语言操作符汇总(上)

目录 前言 一、操作符的分类 二、⼆进制和进制转换 1. 二进制转10进制 2. 10进制转2进制数字 3.  2进制转8进制和16进制 3.1 2进制转8进制 3.2 二进制转16进制  三、原码、反码、补码  四、移位操作符 1. 左移操作符 2. 右移操作符  五、位操作符:&、|、^、~ 1.按位与: 2.按位或:  3.异或 4.按位取反   5.趁热

Versioned Staged Flow-Sensitive Pointer Analysis

VSFS 1.Introduction2.Approach2.1.相关概念2.2.VSFS 3.Evaluation参考文献 1.Introduction 上一篇blog我介绍了目前flow-sensitive pointer analysis常用的SFS算法。相比IFDS-based方法,SFS显著通过稀疏分析提升了效率,但是其内部依旧有许多冗余计算,留下了很大优化空间。 以

Flink实战案例(二十三):自定义时间和窗口的操作符(四)window functions之增量聚合函数(一)ReduceFunction

实例一 例子: 计算每个传感器15s窗口中的温度最小值 val minTempPerWindow = sensorData.map(r => (r.id, r.temperature)).keyBy(_._1).timeWindow(Time.seconds(15)).reduce((r1, r2) => (r1._1, r1._2.min(r2._2))) 实例二 ReduceFun

Flink实战案例(二十二):自定义时间和窗口的操作符(三)CoProcessFunction

CoProcessFunction   对于两条输入流,DataStream API提供了CoProcessFunction这样的low-level操作。CoProcessFunction提供了操作每一个输入流的方法: processElement1()和processElement2()。   类似于ProcessFunction,这两种方法都通过Context对象来调用。这个Conte