如何使用协程重构/替换回调实现



尝试用协程替换使用回调。 有一个使用回调的实现,如果协程可以提供帮助,不确定正确的方法是什么。

这是带有回调的实现。 它有一个类repository,用于提供来自本地数据库或网络远程的数据。

class Repository() {
var callback = //callback is provided by the caller
var isReady = false
var data = null
var firstimeCall = true  //only need to get from database at first time call
fun getData(cb: ICallback) {
callback = cb
isReady = false
if (firstimeCall) {
firstimeCall = false
data = doGetDataFromDatabase()  //sync call to get data from database
isReady = true
callback.onComplete(this)
}
isReady = false
data = doGetDataFromNetwork() {// async call and lamda as the callback
isReady = true
saveToDatabase(data)
callback.onComplete(this)
}
}
}

repository.getData()可以多次调用,只有第一次它会先从数据库返回数据,然后 从网络获取并保存,然后调用 callback.onComplete() 返回数据。

任何其他时间,它只会通过回调从网络获取/保存/返回数据。

用例包括:

  1. 直接使用Repository,例如
repository.getData()  -- 1st time call
repository.getData()  -- later call it again
  1. 有多个repositories,每个数据的数据将被聚合成最终数据。

对于这种情况,有一个Aggregator来保存repositories,并提供onComplete()回调来处理数据,如果所有repositories已经准备好了。

class Aggregator {
var repos = ArrayList<Repository>()
fun getData() {
for (r in repos) {
Thread {
r.getData(callback)
}.start()
}
}
fun processData(data: ArrayList()) {
......
}
val callback = object ICallback (onComplete{repo->
val hasAllComplete = repos.all {
it.isReady
}
if (hasAllComplete) {
var finalData = ArrayList<Data>()
for (r in repos) {
finalData.add(r.data)
}
processData(finalData)
}
})
}

因此,在它有两个Repository的情况下,Aggregator.getData()将从两个存储库获取数据。 当一个Repository完成其getData()调用时,它将回调回调的 onComplete(),其中Aggregator将检查所有repositories是否准备好处理数据。

相同的回调流也用于网络调用。

问题:

在这种情况下如何更改为使用协程,以便只有在从数据库获取数据后才完成两个repositories, 然后它将开始从网络获取数据,而不使用回调。

我不确定它是否相关,但你可以看看 callbackFlow。

更多信息在这里: https://medium.com/@elizarov/callbacks-and-kotlin-flows-2b53aa2525cf#1aaf

我有一个类似的问题,我认为这可能是它的解决方案。

在实际使用它之前,请确保您还阅读了有关 Flow 及其用法的更多信息,因为处理异常(异常透明度)等有一些注意事项。

最新更新