我目前正在一个项目中从RxJava切换到Kotlin协程,用协程等效项替换所有的Single和Observable返回类型。我仍然在努力与以下结构:接口(例如存储库的接口)提供数据查询访问并返回RxJava Single。该实现使用Single.create创建一个Single对象,并使用onSuccess / onError发出结果。现在,实现需要检索数据的方法是创建带有回调的侦听器,并将该侦听器注册到某种内容。然后,该创建的侦听器的回调将在自制Single上调用onSuccess / onError。例如使用firebase(尽管我的问题不是特定于firebase的):
interface Repository {
fun getData(query: Query): Single<DataSnapshot?>
}
fun getData(query: Query): Single<DataSnapshot?> = Single.create { emitter ->
query.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onCancelled(error: DatabaseError?) {
emitter.onError(Exception())
}
override fun onDataChange(data: DataSnapshot?) {
emitter.onSuccess(data)
}
})
}
现在我想拥有的是返回协程Deferred的接口方法。如何创建实现,以便还可以在回调中注册一个侦听器,然后其结果将由Deferred传递?我看不到这些协程构建器(如异步,启动等)如何执行onSuccess / onError会做的事情。
interface Repository {
fun getData(query: Query): Deferred<DataSnapshot?>
}
我的建议如下:
interface Repository {
suspend fun getData(query: Query): Result<DataSnapshot>
}
其中Result可能是带有Success和Error案例的密封类:
sealed class Result<T> {
class Success<T>(result: T) : Result<T>()
class Error<T>(error: String) : Result<T>()
}
这样,在getData的实现方面,您可以执行以下操作:
return Success(yourData)
要么
return Error("Something went wrong")
通常,在处理协程时,应避免返回延迟并尝试将它们“用作同步方法”。
编辑:现在,我了解了问题,希望对您有所帮助:
//This is as generic as it gets, you could use it on any Query, no need to retype it
suspend fun Query.await(): DataSnapshot = suspendCoroutine{cont ->
addListenerForSingleValueEvent(object : ValueEventListener{
override fun onCancelled(error: DatabaseError?) {
cont.resumeWithException(error?: Exception("Unknown Error"))
}
override fun onDataChange(data: DataSnapshot?) {
if(data != null){
cont.resume(data)
} else {
cont.resumeWithException(Exception("Null data"))
}
}
})
}
//this is your actual implementation
suspend fun getData(query: Query):DataSnapshot =
query.await()
此代码假定DatabaseError扩展了Exception或Throwable。如果不是这样,您将需要为其创建包装类型,或者使用我的原始解决方案并在两种情况下都使用常规简历。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句