1
votes

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
    }}
2
I know you said no LiveData, but have you considered developer.android.com/reference/androidx/lifecycle/… for this? - Bink
@Bink Thanks bro for your interest, I read about it before and i will consider it in later projects . - Ahmed Atwa

2 Answers

4
votes

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)
}
0
votes

you can use any asynchronous and event-based library to do it.

You can use rx-java publish subject : 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)
}

you can subscribe to this subject where ever you want the data

you can use flows as already mentioned bu @jsamol

you can use live data as well.