Exciting secrets about MVVM that nobody tells you
After working in several android projects with many different architecture and patterns I had realized that it's not just about MVC, MVP or MVVM, actually it's just the begin. In this article I will try to explain why MVVM alone isn't enough.
So lets start with MVVM.
As the majority knows, MVVM is an acronym to Model, View, ViewModel, in other words it means:
- Model should represent your application domain model.
- View represents your layout/appearence (activity/fragment…).
- ViewModel should act as an intermediate between Model and View. It's important to mention that ViewModel shouldn't knows anything about android frameworks(context/view), it should has only java/kotlin implementations, handle the view logic presentation and view data. Not having view’s reference within viewmodel allow to implement test much easier and prevent unexpected crashes.
Said that, lets talk a little about ViewModel and LiveData from Android Architecture Component launched by Google. The innovation of this components are basically that they are lifecycle aware.
Lifecycle Aware?
For example, when device rotation happens, some activity's method such as oncreate, onstop, ondestroy is triggered. All these event compose the activity lifecycle, so when the component is lifecycle aware means that the component knows how handle this event.
What is the problem about being lifecycle unaware?
Usually viewmodel are created inside these lifecycle events, then viewmodel’s new instance would be created each time that the event is triggers (ex: device rotate). Also viewmodel class could load some initial data to show in view, so the load method would also be triggered each time that rotation happens making the app heavier. It all happens because the viewmodel is lifecycle unaware.
It could still be worse
Knowing that view can be recreated any time while viewmodel could still be loading some initial data, when viewmodel’s loading is over, the viewmodel could try to do something with the view’s reference already destroyed, it would probably lead to memory leak or app crash (Tip: Avoid view’s reference in viewmodel.). So how can we solve this?
ViewModel — Android Architecture Component
Viewmodel component is lifecycle aware, in other words, it won’t be destroyed each time that some view lifecycle event are triggered, it is possible because the viewmodel has an Activity/Fragment’s lifecycle owner and then it will survive configuration changes such as screen rotations.
Example: Lets say that screen is rotated while the viewmodel is still loading the view data, then the viewmodel will keep loading and return the data to view without any impact of screen rotation. If viewmodel wasn’t lifecycle aware, after the screen rotation, would be necessary to load the view data again because the viewmodel would be recreated together with the view.
Another example: If the activity is finished while viewmodel was still loading some data, then when over, viewmodel won’t return the data to view because it knows that the view component was already finished, avoid some memory leak.
Cool, so we are using MVVM pattern together with viewmodel component that handle lifecycle and help to avoid memory leak and app crash, then what comes next?
Massive ViewModel
Some day in your happy coding life you meet a massive viewmodel, in other words it's a viewmodel that does much more than it should.
Let’s says that viewmodel began to has business logic, APIs calls, database connection… It’s exactly what it shouldn’t be doing. So how can we split the responsibilities?
Reactive architecture: Data, Domain and Presentation layer.
- Data Layer: Here you will find class that handle API requests, database access, connections, persistence things, mapped entities… A pattern to use in this layer is know as Repository.(https://martinfowler.com/eaaCatalog/repository.html)
- Domain Layer: At this layer, you should find objects that handle application’s business logic, domain model, rules… A good approach is to use Services and Domain Model and be careful with anemic domain model. (https://www.martinfowler.com/bliki/AnemicDomainModel.html https://martinfowler.com/eaaCatalog/serviceLayer.html / https://martinfowler.com/eaaCatalog/domainModel.html)
- Presentation Layer: In this layer you will find the MVVM things, view, viewmodel, components, adapters, activities, fragment…
- Tip: Entities (from data layer) shouldn’t move to others layers such as presentation, it should be mapped from data to domain layer and then it can be moved between layers. https://martinfowler.com/eaaCatalog/dataMapper.html
LiveData — Android Architecture Component
As we are taking in use viewmodel component that handle lifecycle gathered with a reactive architecture, it’s time to make these new layer lifecycle aware, otherwise we are also giving a chance to this layer lead to memory leak or crashes.
LiveData component is an observer data holder that ensure application’s update happens only with component that are in active state. So lets says that the viewmodel class make some request and will wait the callback result. If for some reason the activity’s lifecycle owner is finished, the viewmodel will be cleared and domain/data class will continue to handle the request, thus when the request is over, the callback could lead to crash or memory leak.
LiveData will allow these layer to also be aware of lifecycle, to know how to use LiveData you can read the follow documentation: (https://developer.android.com/topic/libraries/architecture/livedata.html)
These are the reasons that make me believe that MV-Wathever alone isn’t enough to develop an application’s architecture well structured, but when gathered with google android architecture components and a clean architecture, the application become easy to use, reusable, testable, maintainable and decoupled.
Please let me know about your opinion in the comments.