In this Repository class there's only one public function called getMovies called directly from the useCase class .
Now the problem is i want this function to return moviesData multiple times from single call ,At first I want to fetch data locally from db and return it then fetch from remote and do some logic & after that logic ends i want to return also the final value how can i do this with coroutines .
The whole solution is in the return line in getMovies func .
Note : this can be done using liveData or rx but i don't wanna go with any of them as it's not good idea to pass livedata through all these layers ending to viewModel .
Here's the repo 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 introduced the stable version of its own cold asynchronous streams - 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)
}