如何解决从iOS收听Kotlin协程流
我已经设置了Kotlin Multiplatform项目,并向其附加了一个SQLDelight数据库。它的所有设置和运行正常,因为我已经使用以下命令在android端对其进行了测试:
commonMain:
val backgroundColorFlow: Flow<Color> =
dbQuery.getColorWithId(BGColor.id)
.asFlow()
.mapToOneNotNull()
使用以下命令在Android项目MainActivity.kt
中触发正常:
database.backgroundColorFlow.onEach { setBackgroundColor(it.hex) }.launchIn(lifecycleScope)
但是当尝试在iOS项目应用委托中访问相同的调用时,我得到以下选项,并且不确定如何使用它们或将它们转换为我的BGColor
对象:
database.backgroundColorFlow.collect(collector: T##Kotlinx_coroutines_coreFlowCollector,completionHandler: (KotlinUnit?,Error?) -> Void)
有人可以帮助我如何使用它吗?
解决方法
因此,通过创建流程助手来解决了这个问题:
import io.ktor.utils.io.core.Closeable
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun <T> Flow<T>.asCommonFlow(): CommonFlow<T> = CommonFlow(this)
class CommonFlow<T>(private val origin: Flow<T>) : Flow<T> by origin {
fun watch(block: (T) -> Unit): Closeable {
val job = Job()
onEach {
block(it)
}.launchIn(CoroutineScope(Dispatchers.Main + job))
return object : Closeable {
override fun close() {
job.cancel()
}
}
}
}
我的backgroundColorFlow
变量的更新如下,以利用此助手:
val backgroundColorFlow: CommonFlow<BGColor> =
dbQuery.getColorWithId(BGColor.id)
.asFlow()
.mapToOneNotNull()
.map { BGColor(it.name) }
.asCommonFlow()
然后我的迅捷工作方式如下:
database.backgroundColorFlow.watch { color in
guard let colorHex = color?.hex else {
return
}
self.colorBehaviourSubject.onNext(colorHex)
}
和android一样:
database.backgroundColorFlow.watch { setBackgroundColor(it.hex) }
希望这可以帮助遇到此问题的任何人。我想将CommonFlow类转换为Flow的扩展,但没有专有的atm知识,所以恕我直言,恕我直言将是一个更好的解决方案
,您可以使用提到的 collect 方法快速完成 FlowCollector 是一个可以实现的协议,用于收集 Flow 对象的数据。
通用示例实现可能如下所示:
class Collector<T>: FlowCollector {
let callback:(T) -> Void
init(callback: @escaping (T) -> Void) {
self.callback = callback
}
func emit(value: Any?,completionHandler: @escaping (KotlinUnit?,Error?) -> Void) {
// do whatever you what with the emitted value
callback(value as! T)
// after you finished your work you need to call completionHandler to
// tell that you consumed the value and the next value can be consumed,// otherwise you will not receive the next value
//
// i think first parameter can be always nil or KotlinUnit()
// second parameter is for an error which occurred while consuming the value
// passing an error object will throw a NSGenericException in kotlin code,which can be handled or your app will crash
completionHandler(KotlinUnit(),nil)
}
}
第二部分是调用 Flow.collect 函数
database.backgroundColorFlow.collect(collector: Collector<YourValueType> { yourValue in
// do what ever you want
}) { (unit,error) in
// code which is executed if the Flow object completed
}
可能你也喜欢写一些扩展函数来增加可读性
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。