如何在Kotlin CoRoutine中编写rx concatArrayEager等价物?

问题描述 投票:1回答:2

我想将我的rxJava代码转换为Kotlin CoRoutine。

下面是代码进行api和db调用,并将数据返回到UI,无论是什么先发生。让我们说一下DB响应是否恰好比api更快。在那种情况下,api响应将继续,直到它接收到与db同步的数据,尽管它可能早先完成了UI更新。

我该怎么办?

class MoviesRepository @Inject constructor(val apiInterface: ApiInterface,
                                        val MoviesDao: MoviesDao) {

fun getMovies(): Observable<List<Movie>> {
    val observableFromApi = getMoviesFromApi()
    val observableFromDb = getMoviesFromDb()
    return Observable.concatArrayEager(observableFromApi, observableFromDb)
}

fun getMoviesFromApi(): Observable<List<Movie>> {

    return apiInterface.getMovies()
            .doOnNext { it ->
                it.data?.let { it1 -> MoviesDao.insertAllMovies(it1) }
                println("Size of Movies from API %d", it.data?.size)
            }
            .map({ r -> r.data })
}

fun getMoviesFromDb(): Observable<List<Movie>> {
    return MoviesDao.queryMovies()
            .toObservable()
            .doOnNext {
                //Print log it.size :)
            }
}

}

kotlin kotlin-extension kotlinx.coroutines
2个回答
0
投票

作为第一步,你应该为你的suspend funApiInterface电话创建MovieDaos。如果他们有一些基于回调的API,您可以关注these official instructions

你现在应该有

suspend fun ApiInterface.suspendGetMovies(): List<Movie>

suspend fun MoviesDao.suspendQueryMovies(): List<Movie>

现在你可以编写这段代码:

launch(UI) {
    val fromNetwork = async(UI) { apiInterface.suspendGetMovies() }
    val fromDb = async(UI) { MoviesDao.suspendQueryMovies() }
    select<List<Movie>> {
        fromNetwork.onAwait { it }
        fromDb.onAwait { it }
    }.also { movies ->
        // act on the movies
    }
}

重点是select调用,它将同时等待Deferreds并对首先完成的那个进行操作。

如果您想确保根据网络的结果采取行动,则需要更多代码,例如:

    val action = { movies: List<Movie> ->
        // act on the returned movie list
    }
    var gotNetworkResult = false
    select<List<Movie>> {
        fromNetwork.onAwait { gotNetworkResult = true; it }
        fromDb.onAwait { it }
    }.also(action)
    if (!gotNetworkResult) {
        action(fromNetwork.await())
    }

只有当它们在网络结果之前进入时,此代码才会对数据结果起作用,它将在所有情况下处理。


0
投票

沿着这些方向的东西应该有效:

data class Result(val fromApi: ???, val fromDB: ???)

fun getMovies(): Result {
    val apiRes = getMoviesFromApiAsync()
    val dbRes = getMoviesFromDbAsync()
    return Result(apiRes.await(), dbRes.await())
}

fun getMoviesFromApiAsync() = async {

    return apiInterface.getMovies()
            .doOnNext { it ->
                it.data?.let { it1 -> MoviesDao.insertAllMovies(it1) }
                println("Size of Movies from API %d", it.data?.size)
            }
            .map({ r -> r.data })
}

fun getMoviesFromDbAsync() = async {
    return MoviesDao.queryMovies()           
}

我不知道你要回来的是什么,所以我只是把???改为。

© www.soinside.com 2019 - 2024. All rights reserved.