How to do parallel network requests in the repository ? MVVM

531 Views Asked by At

I am working on an Android project and at the moment we are doing multiple network calls in a single repository, for example in the PostsRepository class there are multiple endpoints that needs to be called e.g. (/getNewspost /getPostPrice and maybe /get) then it returns a large Post data class back to the ViewModel.

Although it seems fine, the downside of this structure is being unable to do parallel network calls in the repository like the features of launch, or async/await which only exists in the ViewModel.

So question is can this logic be moved to the ViewModel so then i can do multiple network calls ? Or if this logic should stay in the repository how can we do parallel calls in the repo?

3

There are 3 best solutions below

0
ghouas abdelhak On BEST ANSWER

With Clean architecture , you can create a UseCase to handle this behavior

1.first way

Class GetPostsUseCase(private val postRepository : PostRepository){

   suspend operator fun invoke():List<Post>{
      // we assume that getPosts() 
      // and getPostsPricies() are also suspend functions
      val posts = postRepository.getPosts()
      val prices = postRepository.getPostPricies()
      return build(posts , prices)
   }

   private fun build(posts,prices) :List<Post>{
      // build your data object here
   }

}

/////// OR ////////

Class GetPostsUseCase(private val postRepository : PostRepository){

   suspend operator fun invoke():List<Post> = withContext(Dispatchers.IO){
    
      val posts = async{postRepository.getPosts()}
      val prices = async { postRepository.getPostPricies() }
      posts.await()
      prices.await()
      return build(posts, prices)
   }

   private fun build(posts,prices) :List<Post>{
      // build your data object here
   }

}
2
SaiFuL SAif On

You can create coroutine in Repository class also.

Class PostsRepository{ 

suspend fun callAPIs() : String{
    return withContext(Dispatchers.IO) {
        val a = async { getPost() }
        val b = async { getNews() }

        return@withContext a.await() + b.await()
    }
}

}

0
Tung Ha On

You can achieve this by using suspend and withContext

class PostsRepository {
    suspend fun fetchPostData(): Post {
        return withContext(Dispatchers.IO) {
            val fetchA = async { getA() }
            val fetchB = async { getB() }
            val fetchC = async { getC() }
            //More if needed ...
        
            //Then execute waitAll() to get them all as parallel
            val (AResult, BResult, CResult) = awaitAll(fetchA, fetchB, fetchC)
        
            //Finally use the result of these fetch when all of them is completed
            return@withContext Post(AResult, BResult, CResult)
        }
    } 
}