Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using clean MVP on android with RxJava: How can you keep the presenter free of any android knowledge while still observing on the UI thread?

In an effort to implement 'clean' architecture on android with the mvp pattern it is advised to treat the android framework as a plugin and not leak any android aware dependencies into the presenter layer. Using rxjava, if I have a presenter that is designed to 'push' data to the view layer I may want to have logic like this:

public interface SearchPresenter {

  interface ViewLayer {
  void updateResults(List<SearchResult> searchResults)
  }
  void bind(ViewLayer viewLayer);
  void unbind();
}

public class SearchPresenterImpl implements SearchPresenter {

   ViewLayer viewLayer;
   CompositeDisposable compositeDisposable;

    @Override
    public void bind(ViewLayer viewLayer) {
      this.viewLayer = viewLayer;

      compositeDisposable = new CompositeDisposable();
      compositeDisposable.add(
            searchInteractor.getSearchResults()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(this::refreshView));

}

private void refreshView(List<SearchResult> searchResults) {
    //send the results back to the view layer to update a RecyclerView      
    viewLayer.updateResults(searchResults)
}

@Override
public void unbind() {
    compositeDisposable.dispose();
}

However, by observing on 'AndroidSchedulers.mainThread()' this forces a dependency on:

import io.reactivex.android.schedulers.AndroidSchedulers

at which point, my presenter now knows about android and is tied to it; which I want to avoid.

What is the advised way to handle this so that the result is guaranteed to be delivered to the ViewLayer on android's UI (Main) thread while the presenter maintains no dependencies on anything android related?

like image 849
JohnRock Avatar asked Dec 23 '22 13:12

JohnRock


1 Answers

AndroidSchedulers.mainThread() uses Android code to schedule actions on the main thread, don't use it directly in your presenter. instead You can refactor the presenter to take Schedulers in its constructor, in production code use the regular AndroidSchedulers.mainThread() and Schedulers.io(), in testing you can just send Schedulers.trampoline() or Schedulers.immediate() .

see this pattern in this example: https://github.com/riggaroo/GithubUsersSearchApp/blob/master/app/src/main/java/za/co/riggaroo/gus/presentation/search/UserSearchPresenter.java

and its test class here: https://github.com/riggaroo/GithubUsersSearchApp/blob/8b83095d7a2cc8f3cb69a945224ab4c37cf54a37/app/src/test/java/za/co/riggaroo/gus/presentation/search/UserSearchPresenterTest.java

like image 175
amr elmasry Avatar answered Dec 27 '22 01:12

amr elmasry