After Google announced android architecture components, it was, for the first time, a Google-approved android architecture guidelines. Before this, the whole community would try to come up with best ways to structure android apps. First, everyone tried to follow MVC pattern that Google sort of provided with Android. But MVC for android is very confusing, you have a controller who is a view also (Activity, Fragment). Then MVP came along. model view presenter architecture, which clearly separates responsibilities of views and presenters (controllers). The main idea was to define interfaces (responsibilities) for each view and its presenter, making the app much easier to refactor down the road, given the fact that you know exactly what are responsibilities of each screen. One downside for MVP is the total amount of interfaces you have to create and maintain.
When reactive java came along, it turned everything upside down. MVP did not fit quite well with rxJava, since data is reactive, you do not have to specify what happens when data changes, you just map it to the view and the view became reactive to its data. With reactive programming, you react to changes in the app, whether its user input or network fetching and the view is this dummy representation of that data. It turned out, that reactive programming is perfect for Android, since events are something that is very natural to mobile phones, it became much easier to write and maintain complex UIs with rxJava. So what are downsides to rxJava? Spaghetti code, if you can not recognize when to use rxJava, it is very easy to write spaghetti code.
So what exactly does architecture components bring to the table?
Architecture components overview
Before we look into what architecture components offer, what problems do they solve, let’s look at common issues Android developers face.
- Configuration change (device rotation),
- Synchronized UI with data
- Fetching data from database
- … (lots more)
Let’s start with the configuration change, what would be a proper way to solve this problem? In my opinion, I want no memory leaks :D, then I would like the data to survive the change, I don’t want to fetch data again just because a user rotated the screen. So we need some kind of lifecycle aware component which survives the configuration change, knows when it can update the activity, but also knows when to destroy itself when it is not needed anymore. This is exactly what ViewModel class is. With few lines of code, you can have a UI that reacts to data changes and also display the latest data when UI gets recreated.
What about UI synchronization? That is where LiveData comes in. Once you create a LiveData instance, you can subscribe to it, and receive updates every time you update that LiveData instance.
What about the database? There are plenty of ORM libraries out there, do we need another one? Well, what if you want an ORM which returns a LiveData, which you can subscribe to it, so when you insert new data into the database, you get updates immediately? That is where Room comes in.
Those are the building blocks of Android architecture components, but the question remains, what about Android architecture? These components serve a specific purpose, how to structure the whole app now?
Well, just follow MVVM architecture, the View reacts to ViewModel, which exposes Models for Views to use and update their representation. Instead of wiring the Views to Models manually, Data-Binding library can be used to that automatically. So what we described above is just a Google recommended/provided implementation of the required components for MVVM architecture.
I made a Github repository for a sample project that uses Kotlin and android architecture components, check it out to see how everything fits together in one app. Here are the main specifications of the project in that repository:
- ViewModel for reactive data binding
- Room as ORM library
- Paging Library as a reactive data source for adapters
- Dagger 2 as dependency injection framework
- Repository pattern for data fetching
- Retrofit as a REST client