MVVM with Dagger 2, Retrofit, RxJava
02 January 2020 • 4 mins read
I used to work with MVP pattern until now. However, when Google released nice-to-use components like the ViewModel along with the Android Jetpack, I have tried to work with MVVM pattern. In this article, we will see how can we use the MVVM pattern with Retrofit, RxJava, and Dagger 2.
What is MVVM?
Model-View-ViewModel architecture consists of 3 parts.
- The View gets user’s actions and sends to the
ViewModel, or listens live data stream from theViewModeland provides to the users. - The ViewModel gets user’s actions from the
Viewor provides data toView. - The Model abstracts the data source.
ViewandViewModeluses that on data stream.
Project Configuration
We implement Android Lifecycle, Retrofit, RxJava, ButterKnife and Dagger 2 libraries in addition to Support libraries.
Setting Up Retrofit Interface
We have used Github API for Json source and as you see Single<> return type in order to observe data with RxJava.
Setting Up Application Class, Base Activity, Base Fragment
We have to use DaggerApplication, DaggerAppCompatActivity and DaggerFragment classes for injecting objects with ContributesAndroidInjector annotation.
We have used abstract layoutRes() function in order to get resource layout id from Activity which extends BaseActivity.
Setting Up Dagger 2 Component & Modules
As you can see, we have wrote only AndroidSupportInjectionModule, ActivityBindingModule and ViewModelModule to the module parameter. We will write other required modules in which Activity or Fragment they needed.
If explain what we have did in that code snippet;
-
provideRetrofit— Provides Retrofit adjusted withbase url, adapter and converter factories.addCallAdapterFactory()function gets adapter factory for supporting service method return types, add instance ofRxJava2CallAdapterFactoryfor RxJava support. -
provideRepoService— Provides Retrofit interface class for making requests.
Creating Custom ViewModel Factory
ViewModelFactory is a factory that extends ViewModelProvider.Factory in order to provide ViewModel instances to consumer fragment classes. We have injected that class with the ViewModelModule.
Setting Up ViewModel
In ViewModel, we will assign the data which loaded with Retrofit to the MutableLiveData. So, how we can use MutableLiveData? We assign the data to MutableLiveData with setValue or postValue methods, and observe this data in LifeCycleOwner (Activity or Fragment). When we make any changes on the MutableLiveData, this change is dynamically declared to the view. Also, It does not oblige us to check whether View is alive in every transaction.
As you can see, we didn’t use any component injecting code, because we have injected all required classes in the MainFragmentBindingModule and also we have did same thing for activities in the ActivityBindingModule.
Setting Up Fragment
As you know, fragment is our View part. We have injected ViewModelFactory and started to observe LiveData objects.
Creating RecyclerView Adapter
In recyclerView adapter, we have only observed List<Repo> LiveData and bind them to the recyclerView.
MVVM vs MVP
Previously I implemented a very similar app using MVP architecture here. Let’s compare the two architectures:
- Goodbye Presenter, Hello ViewModel! ViewModel in MVVM is an equivalent to Presenter in MVP architecture. MVP contains slightly more code. For instance, my Presenter extended a common base Presenter. I had View and Presenter interfaces and Contract interface to tie them together.
- In MVP Activity#onSaveInstanceState() and Activity#onRestoreInstanceState() callbacks can be used to save state between configuration changes such as device rotation. If you use the new architecture component ViewModel in MVVM, data survives rotations automatically.
- MVP requires tighter component coupling. The Presenter keeps a reference to the View, albeit via an interface. It is necessary because the View often needs to inform the Presenter of lifecycle events such as onStop() or onDestroy() so that the Presenter can clear RxJava Subscriptions, etc. In MVVM you simply override ViewModel#onCleared() to do the cleanup without the View getting involved.
- In MVP, the View delegates all the work to the Presenter and the latter then tells the View what results to display. Similarly, in MVVM, the View delegates all the work to the ViewModel but then the View observes and reacts to the responses from the ViewModel.
- While there is no one-size-fits-all when it comes to Android apps, for the reasons outlined above, MVVM architecture seems to have an advantage over MVP. While both are great at keeping business logic away from the View, abstracting data layer and making the code highly testable and maintainable, going forward, whenever I architect a new Android application, I will likely consider MVVM first
Thanks a lot for reading, Happy coding :)