What is the android efficient way to chain operation on Livedata/MediatorLiveData in multiple network call scenario?

289 Views Asked by At

In my todoApp I've implemented MediatorLiveData for learning purpose in the following manner:

    private val todoListMediator = MediatorLiveData<NetworkResult<List<TodoEntity>>>()
 

    private var todoSource: LiveData<NetworkResult<List<TodoEntity>>> =
        MutableLiveData()
    val todoResponse: LiveData<NetworkResult<List<TodoEntity>>> get() = todoListMediator

    viewModelScope.launch(dispatcherProvider.main) {
        
        todoSource =
            todoRepository.getTodoList()
        todoListMediator.addSource(todoSource) { 
            todoListMediator.value = it
        }
    }

The above code works fine. Now I wanna make following changes and I don't have clear picture how can I achieve them.

  • As soon as todoListMediator.addSource() observes the todoList: 1] I want to iterate over that original Todo list and make a network call for each element and add some more field to them. 2] I wanna save the new todo list(where each Todo now has some extra field we received by network call in step 1) 3] and finally, I want to assign that new todo list(with extra field) to the todoListMediator.

      // sudo to illustrate the above scenario 
     viewModelScope.launch(dispatcherProvider.main) {
                 //step.1 get original todo list
                 todoListMediator.addSource(todoSource) { it ->
    
                 // step 2. iterate over original todo list from step 1 and make network call to get extra field for each element and update the original list
                 //for example
                 val newFieldForTodoElement =  NetworkResult<PendingTodoValues?> = todoRepository.getPendingTodoValues()
    
                 // step 3. one all the original list is updated with new field values, save the Todo list in local db
    
                 // step 4. Then pass the todo list with new fields to mediator live data from db
                 todoListMediator.value = it
                 }
             }
    

Any tricks with detailed explanation on code will be a great help for my learning. Thanks!

1

There are 1 best solutions below

0
user3185978 On

you can use RXjava with Flatmap operator

something like that may help ?

  getPostsObservable()
            .subscribeOn(Schedulers.io())
            .flatMap(new Function<Post, ObservableSource<Post>>() {
                @Override
                public ObservableSource<Post> apply(Post post) throws Exception {
                    return getCommentsObservable(post);
                }
            })
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<Post>() {
                @Override
                public void onSubscribe(Disposable d) {
                    disposables.add(d);
                }

                @Override
                public void onNext(Post post) {
                    updatePost(post);
                }

                @Override
                public void onError(Throwable e) {
                    Log.e(TAG, "onError: ", e);
                }

                @Override
                public void onComplete() {
                }
            });
}

private Observable<Post> getPostsObservable(){
    return ServiceGenerator.getRequestApi()
            .getPosts()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .flatMap(new Function<List<Post>, ObservableSource<Post>>() {
                @Override
                public ObservableSource<Post> apply(final List<Post> posts) throws Exception {
                    adapter.setPosts(posts);
                    return Observable.fromIterable(posts)
                            .subscribeOn(Schedulers.io());
                }
            });
}

private void updatePost(final Post p){
    Observable
            .fromIterable(adapter.getPosts())
            .filter(new Predicate<Post>() {
                @Override
                public boolean test(Post post) throws Exception {
                    return post.getId() == p.getId();
                }
            })
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<Post>() {
                @Override
                public void onSubscribe(Disposable d) {
                    disposables.add(d);
                }

                @Override
                public void onNext(Post post) {
                    Log.d(TAG, "onNext: updating post: " + post.getId() + ", thread: " + Thread.currentThread().getName());
                    adapter.updatePost(post);
                }

                @Override
                public void onError(Throwable e) {
                    Log.e(TAG, "onError: ", e);
                }

                @Override
                public void onComplete() {
                }
            });
}

private Observable<Post> getCommentsObservable(final Post post){
    return ServiceGenerator.getRequestApi()
            .getComments(post.getId())
            .map(new Function<List<Comment>, Post>() {
                @Override
                public Post apply(List<Comment> comments) throws Exception {

                    int delay = ((new Random()).nextInt(5) + 1) * 1000; // sleep thread for x ms
                    Thread.sleep(delay);
                    Log.d(TAG, "apply: sleeping thread " + Thread.currentThread().getName() + " for " + String.valueOf(delay)+ "ms");

                    post.setComments(comments);
                    return post;
                }
            })
            .subscribeOn(Schedulers.io());