创建发出侦听器回调结果的Kotlin协程Deferred对象

Lemao1981

我目前正在一个项目中从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?>
}
埃里克·马托里(Eric Martori)

我的建议如下:

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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章