return 使用 kotlin 协程从单个函数多次
return multiple times from single function using kotlin co routines
在此存储库 class 中,只有一个 public 函数直接从 useCase class 调用 getMovies 。
现在的问题是我希望这个函数从一次调用中多次 return moviesData ,起初我想从 db 本地获取数据 return 然后从远程获取数据并做一些逻辑 & 在逻辑结束后我想 return 也是最终值我怎么能用协同程序做到这一点。
整个解决方案在 getMovies func 的 return 行中。
注意:这可以使用 liveData 或 rx 来完成,但我不想使用它们中的任何一个,因为将 livedata 通过所有这些层结束到 viewModel 并不是一个好主意。
这是回购 class :
@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
}}
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)
}
您可以使用任何异步和基于事件的库来完成。
您可以使用 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)
}
您可以在任何需要数据的地方订阅此主题
您可以使用已经提到的流 bu @jsamol
您也可以使用实时数据。
在此存储库 class 中,只有一个 public 函数直接从 useCase class 调用 getMovies 。
现在的问题是我希望这个函数从一次调用中多次 return moviesData ,起初我想从 db 本地获取数据 return 然后从远程获取数据并做一些逻辑 & 在逻辑结束后我想 return 也是最终值我怎么能用协同程序做到这一点。
整个解决方案在 getMovies func 的 return 行中。
注意:这可以使用 liveData 或 rx 来完成,但我不想使用它们中的任何一个,因为将 livedata 通过所有这些层结束到 viewModel 并不是一个好主意。
这是回购 class :
@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
}}
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)
}
您可以使用任何异步和基于事件的库来完成。
您可以使用 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)
}
您可以在任何需要数据的地方订阅此主题
您可以使用已经提到的流 bu @jsamol
您也可以使用实时数据。