从 iOS 收听 Kotlin 协程流程
Posted
技术标签:
【中文标题】从 iOS 收听 Kotlin 协程流程【英文标题】:Listen to Kotlin coroutine flow from iOS 【发布时间】:2021-01-18 08:10:13 【问题描述】:我已经设置了一个 Kotlin 多平台项目并附加了一个 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)
谁能帮我看看这个怎么用?
【问题讨论】:
您找到解决方案了吗?我遇到了同样的问题。 是的,我有!给我几分钟时间回答:) 【参考方案1】:所以这通过创建一个流助手来解决:
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
var 更新如下以使用此助手:
val backgroundColorFlow: CommonFlow<BGColor> =
dbQuery.getColorWithId(BGColor.id)
.asFlow()
.mapToOneNotNull()
.map BGColor(it.name)
.asCommonFlow()
然后我的 swift 工作如下:
database.backgroundColorFlow.watch color in
guard let colorHex = color?.hex else
return
self.colorBehaviourSubject.onNext(colorHex)
和安卓一样:
database.backgroundColorFlow.watch setBackgroundColor(it.hex)
希望这可以帮助遇到此问题的任何人。我想将 CommonFlow 类转换为 Flow 的扩展,但没有专业知识 atm,所以如果有的话,恕我直言,这将是一个更好的解决方案
【讨论】:
【参考方案2】:您可以使用上面提到的收集方法快速完成 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
可能你也喜欢写一些扩展函数来增加可读性
【讨论】:
完美,只需将 FlowCollector 替换为 Kotlinx_coroutines_coreFlowCollector以上是关于从 iOS 收听 Kotlin 协程流程的主要内容,如果未能解决你的问题,请参考以下文章