【问题标题】:return multiple times from single function using kotlin co routines使用 kotlin 协程从单个函数多次返回
【发布时间】:2019-12-29 10:03:33
【问题描述】:

在这个 Repository 类中,只有一个名为 getMovies 的公共函数直接从 useCase 类调用。

现在的问题是我希望这个函数从一次调用中多次返回moviesData,首先我想从数据库本地获取数据并返回它然后从远程获取并执行一些逻辑&在逻辑结束后我想返回也是最终值我怎么能用协程做到这一点。

整个解决方案在 getMovies func 的返回行中。

注意:这可以使用 liveData 或 rx 来完成,但我不想使用它们中的任何一个,因为将 livedata 通过所有这些层传递到 viewModel 并不是一个好主意。

这里是 repo 类:

@Singleton
class MovieRepository @Inject constructor(
        private val movieDao: MovieDao,
        private val movieApi: MovieApi,
        private val trailerApi: TrailerApi) : BaseRepository() {

    suspend fun getMovies(): ArrayList<Movie> {
        val localData = fetchMoviesLocal()
        val remoteData = fetchMoviesRemote()
        val syncedData = storeMoviesLocal(remoteData)
        return localData then syncedData
    }

    private fun fetchMoviesLocal(): ArrayList<Movie> = movieDao.fetchAllMovies()

    private suspend fun fetchMoviesRemote(): ArrayList<Movie>? {
        val data = safeApiCall({ movieApi.getMostPopular(AppConstants.API_KEY) },
                "fetching movies")
        return if (data != null) data.results as ArrayList<Movie> else null
    }

    private fun storeMoviesLocal(results: List<Movie>?): ArrayList<Movie>? {
        return if (!results.isNullOrEmpty()) syncFavWithDb(results) else null
    }

    private fun syncFavWithDb(movies: List<Movie>): ArrayList<Movie> {
        val tempList = ArrayList<Movie>()
        movies.forEach { movie -> movie.isFav = if (isMovieLiked(movie.id)) 1 else 0; tempList.add(movie) }
        movieDao.insertAll(tempList)
        return tempList
    }}

【问题讨论】:

标签: android kotlin repository kotlin-coroutines clean-architecture


【解决方案1】:

Kotlin 1.3 引入了自己的冷异步流的稳定版本 - Flows

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow

fun getMovies(): Flow<List<Movie>> = flow {
    val localData = fetchMoviesLocal()
    emit(localData)

    val remoteData = fetchMoviesRemote()
    val syncedData = storeMoviesLocal(remoteData)
    emit(syncedData)
}

【讨论】:

    【解决方案2】:

    您可以使用任何异步和基于事件的库来执行此操作。

    您可以使用 rx-java 发布主题:subjects rx-java

    val subject = PublishSubject(); 
    
    fun getMovies(): Flow<List<Movie>> = flow {
        val localData = fetchMoviesLocal()
        emit(localData)
    
        val remoteData = fetchMoviesRemote()
        val syncedData = storeMoviesLocal(remoteData)
        subject.onNext(syncedData)
    }
    

    您可以在任何需要数据的地方订阅此主题

    你可以使用前面提到的流程 @jsamol

    您也可以使用实时数据。

    【讨论】:

    • 谢谢兄弟,我知道可以使用 Rx 和 livedata 来完成,正如我在问题中提到的 @jsamol 答案是正确的。
    猜你喜欢
    • 2019-10-10
    • 1970-01-01
    • 2020-12-08
    • 1970-01-01
    • 1970-01-01
    • 2019-05-11
    • 1970-01-01
    • 2020-03-12
    • 2018-02-22
    相关资源
    最近更新 更多