Kotlin协程flow发送时间间隔debounce

22 篇文章 0 订阅

Kotlin协程flow发送时间间隔debounce

debounce的作用是让连续发射的数据之间间隔起来。典型的应用场景是搜索引擎里面的关键词输入,当用户输入字符时候,有时候,并不希望用户每输入任何一个单字就触发一次后台真正的查询,而是希望用户在输入一定时间间隔后(猜测此时用户已完成完整关键词的输入),才真正发送最后一次的输入。debounce蕴含了一定的缓冲思想,即,不立刻触发事件,而是先把要发射的数据进入队列,稍等一定时间(时间)延迟触发,而触发的重要条件取决于前一条数据和后一条数据的时间间隔,注意,前一条和后一条尚未被发射出去,只是待命中。如果连续两次间隔时间满足timeOut,只保留最后一条数据。

 

import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking

fun main(args: Array<String>) {
    val timeOut = 100L

    runBlocking {
        val result = userInput()
            .debounce(timeOut).collect {
                println(it)
            }
    }
}

fun userInput() = flow {
    emit("A")
    delay(100)
    emit("AB")
    delay(150)
    emit("ABC")
    delay(200)
    emit("ABCD")
    delay(100)
    emit("ABCDE")
}

 

当timeOut=100

AB
ABC
ABCD
ABCDE

A和AB都待发射,A和AB间隔100,所以跳过A,直接发射AB。

发射完AB后,由于ABC与之前的AB间隔超过100,继续发射。

 

 

 

 

当timeOut=150,比较难理解。

AB
ABC
ABCDE

A待发射,Kotlin发现A与AB间隔才100,所以舍弃A,Kotlin发现从A开始到AB之后的ABC,AB的等待时间超过150,且之前的A没有发射,所以发射AB。

发射完AB,下一个ABC与AB之间间隔150,且ABC与其后仍有时间间隔,继续发射ABC。

发射完ABC,Kotlin审视待发射的ABCD,按理说ABCD与ABC间隔200,满足发射timeOut值,但是ABCD与ABCDE间隔100,所以跳过ABCD,直接发射ABCDE。这里特别注意,Kotlin发射当前数据时候,是要把这条数据的前一条、后一条都拉通看的。

 

 

 

当timeOut=200

ABC
ABCDE

A与AB间隔100,舍弃A。而AB与之前的A间隔100,与之后的ABC间隔150,小于timeOut值,舍弃。ABC与之前的AB有时间间隔,与之后的ABCD间隔刚好等于timeOut值,所以发射。

 

 

 

当timeOut=250

ABCDE

 

简单的说,Kotlin用debounce发射当前数据时候,这个数据的前一条数据和后一条数据必须满足时间间隔才能发射,否则舍弃。

 

Kotlin协程flow,firstOrNull只要最先first,lastOrNull只要最后_zhangphil的博客-CSDN博客firstOrNull() //虽然发射很多数据,但只要第1次发射过来的数据。.lastOrNull() //虽然发射很多数据,但只要最后1次发射过来的数据。emit(i)delay(10)kotlin协程flow任务意外结束未emit数据retryWhen onEmpty(5)_zhangphil的博客-CSDN博客一、flow ,emit,onCompletion,collect。https://blog.csdn.net/zhangphil/article/details/132492588kotlin协程flow filter map flowOn zip combine(1)_zhangphil的博客-CSDN博客一、flow ,emit,onCompletion,collect。四、map,重组改写数据。八、conflate 合并。九、debounce去重。二、函数作为flow。https://blog.csdn.net/zhangphil/article/details/130084723

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 Kotlin 协程 TCP 发送接收 demo: ```kotlin import kotlinx.coroutines.* import java.net.InetSocketAddress import java.net.Socket import java.nio.ByteBuffer import java.nio.channels.AsynchronousChannelGroup import java.nio.channels.AsynchronousSocketChannel import java.util.concurrent.Executors suspend fun sendAndReceive() { val group = AsynchronousChannelGroup.withThreadPool(Executors.newSingleThreadExecutor()) val socket = AsynchronousSocketChannel.open(group) socket.connect(InetSocketAddress("localhost", 12345)).await() // 发送数据 val buffer = ByteBuffer.wrap("Hello, server!".toByteArray()) socket.write(buffer).await() // 接收数据 val receiveBuffer = ByteBuffer.allocate(1024) socket.read(receiveBuffer).await() receiveBuffer.flip() val receivedData = String(receiveBuffer.array(), 0, receiveBuffer.limit()) println("Received data: $receivedData") socket.close() group.shutdown() } fun main() = runBlocking { sendAndReceive() } ``` 在上面的代码中,我们创建了一个 `AsynchronousChannelGroup`,用于管理异步通道。然后我们打开一个异步 socket 通道,并连接到服务器。接着,我们将要发送的数据封装成一个 byte buffer,并使用 `await()` 方法来等待 socket 写入操作完成。然后我们再创建一个接收数据的 byte buffer,并使用 `await()` 方法等待 socket 读取操作完成。最后,我们将接收到的数据转换成字符串并打印出来。最后,我们关闭 socket 和 channel group。 需要注意的是,在上面的代码中,我们使用了 `runBlocking` 来运行协程,这将阻塞当前线程直到所有协程都完成。如果您的应用程序中已经有一个事件循环,您也可以使用 `GlobalScope.launch` 来运行协程,从而不会阻塞当前线程。 另外,还要注意在使用协程时需要导入以下依赖: ```gradle implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:x.x.x") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-nio:x.x.x") ``` 其中,`x.x.x` 表示您使用的 Kotlin 协程库的版本号。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值