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

时间:2019-07-03 18:40:50

标签: kotlin-coroutines

尝试用协程替换using回调。有了使用回调的实现,并且不确定协程可以提供帮助的正确方法。

这是带有回调的实现。 它有一个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的数据库中获取数据之后, 然后它将开始从网络获取数据,而无需使用回调。

1 个答案:

答案 0 :(得分:1)

我不确定它是否有意义,但是您可以看看callbackFlow

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

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

在实际使用Flow之前,请确保还了解有关Flow及其用法的更多信息,因为在处理异常(异常透明性)等方面存在一些警告。