android - 您能否创建一个协程 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
再次激活以同时发出这些值?
解决方案
您可以尝试以下一些选项:
BroadcastChannel<String>(Channel.BUFFERED).asFlow()
,这将使用 的容量初始化您的通道,默认情况下DEFAULT_BUFFER_PROPERTY_NAME
为64,但可以在 JVM 上覆盖。- 您可以创建
Channel(Channel.UNLIMITED)
thenconsumeAsFlow()
,但是是的,拥有无限缓冲区通常是一种不好的做法 - 创建一个
Channel(Channel.RENDEZVOUS)
, 并使用send()
而不是offer()
. 集合通道基本上是容量为 0 的通道,只要您的值没有被消耗/收集,它就会暂停send()
呼叫。
推荐阅读
- javascript - 自定义四舍五入到最接近的 0.05
- c++ - C++,释放已经释放不会产生编译器错误
- string - 将字符串解析为二进制元组列表
- android - 对 Android 应用的测试和生产版本使用不同的后端
- python - 根据另一列的值在 pandas 的列中创建值列表
- c# - FastReport 嵌套 C# 类变量未使用
- python - 函数内字符串和整数名称的连接(python3)
- java - 远程调试:OpenJDK 11 上的 Wildfly 14 在端口 8787 上没有连接
- go - 为什么编译器会在这种情况下抱怨一个未使用的变量(当它被 fmt.Fprintf 使用时)?
- c# - 在 .csproj 中包含一个 .targets 文件以全局定义项目和 MSBuild 变量