首页 > 解决方案 > 您能否创建一个协程 BufferedBroadcastChannel 来存储接收到的值,即使在 Android 中未使用时也是如此?

问题描述

我有一个库,它通过从不同来源读取数据产生值,并将它们提供给库用户可以从中收集的流

为此,我使用此代码

private val dataChannel = BroadcastChannel<Reading>(10) 

val dataFlow get() = dataChannel.asFlow()

//this may be triggered by a 5 different threads
fun newReading(type:String, value:Float, time:Date, level:Int) {
    dataChannel.offer(Reading(type,value,time,Level.fromValue(level))
}

用户可以做这样的事情来获取数据

lastJob?.cancel()
lastJob = launch {
    lib.dataFlow.flowOn(Dispatchers.Default).collect { reading ->
       val result = processReading(reading)
       withContext(Dispatchers.IO) {
           Toast.makeText(application.applicationContext, result,Toast.LENGTH_LONG).show()
       }
    }
}

这按预期工作,当用户启动作业时,我的图书馆可能会继续发送数据并且图书馆的用户将继续接收它们

但是,如果用户取消lastJob并在几秒钟后再次启动它,他们将丢失我的库在这两次之间接收到的数据

是否可以dataChannel存储在该时间跨度内接收到的所有读数offer(直到其构造函数中设置的缓冲级别 10)以及何时dataFlow再次激活以同时发出这些值?

标签: androidkotlin-coroutineskotlin-coroutine-channel

解决方案


您可以尝试以下一些选项:

  1. BroadcastChannel<String>(Channel.BUFFERED).asFlow(),这将使用 的容量初始化您的通道,默认情况下DEFAULT_BUFFER_PROPERTY_NAME64,但可以在 JVM 上覆盖。
  2. 您可以创建Channel(Channel.UNLIMITED)then consumeAsFlow(),但是是的,拥有无限缓冲区通常是一种不好的做法
  3. 创建一个Channel(Channel.RENDEZVOUS), 并使用send()而不是offer(). 集合通道基本上是容量为 0 的通道,只要您的值没有被消耗/收集,它就会暂停send()呼叫。

推荐阅读