尝试用协程替换使用回调。 有一个使用回调的实现,如果协程可以提供帮助,不确定正确的方法是什么。
这是带有回调的实现。 它有一个类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() 返回数据。
任何其他时间,它只会通过回调从网络获取/保存/返回数据。
用例包括:
- 直接使用
Repository
,例如
repository.getData() -- 1st time call
repository.getData() -- later call it again
- 有多个
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 及其用法的更多信息,因为处理异常(异常透明度)等有一些注意事项。