This sample project provides several examples of using modern architecture approaches.
For instance, it uses:
- MVVM architectural pattern
- Architecture Components:
- LiveData
- ViewModel
- Room
- Data Binding
In addition, some examples use:
- ConstraintLayout
- RecyclerView
- ViewHolder
- DiffUtil
The project consists of several parts. I tried to make them as simple as possible, so each of them focuses on a particular functionality and nothing more.
Therefore you can easily appeal to a certain part to figure out how to implement similar functionality in your own app.
Unlike the official Android Architecture Components samples, this project is intended to demonstrate how to implement certain cases you faces in the real life. It's more like tips, not complete apps. All these tips are implemented within a single app.
Before you get into the examples, I recommend to read/watch the following awesome tutorials. I sorted them in the order I think is the best for learning.
So go ahead!
- Android Jetpack: ViewModel
- Android Jetpack: LiveData
- LiveData Clean Code using MVVM and Android Architecture Components
- LiveData with SnackBar, Navigation and other events (the SingleLiveEvent case)
- Android Architecture: Communication between ViewModel and View
- ViewModels and LiveData: Patterns + AntiPatterns
Considering the links above now we can imagine how the architecture should look like:
Here's a summary explanation of the different classes in the diagram, starting from the top:
UI Controllers are activities or fragments in conjunction with corresponding XML-files if present. The only job of UI controllers is to know how to display data and pass on UI events, such as the user pressing a button.
Note! UI Controllers neither contain the UI data, nor directly manipulate data. Don't modify ViewModel's data directly from the UI, even if it looks much simpler, than implement a handler within ViewModel.
These classes represent all of the data needed for the UI to display. ViewModels doesn't know anything about the UI. It just provides reactive fields that UI can observe and update itself. To perform ViewModel-to-UI communication use one of reactive patterns like SingleLiveEvent or Event wrapper.
This class is the single source of truth for all of our app's data and acts as a clean API for the UI to communicate with. ViewModels simply request data from the repository. They do not need to worry about whether the repository should load from the database or network, or how or when to persist the data. The repository manages all of this. As part of this responsibility, the repository is a mediator between different data sources.
Note! This architecture stresses that each class in the diagram only stores a reference to the class or classes directly "below it" and not any classes above it. This means the ViewModel class will store a reference to the Repository class, but not to the UI controller class above it or the Remote Data Source class two levels below it.
Now you're ready to explore the examples of this project.
This part demonstrates how to create a regular user input form in a reactive way.
It actively uses Data Binding, Two-Way Data Binding and binding expressions. The state of the form is perfectly persistent across configuration changes, thanks to ViewModel. It also utilizes Google's SingleLiveEvent to display a Toast after the form is submitted.
Here we create a reactive and efficient list of items.
It uses RecyclerView, Adapter and ViewHolder in conjustion with ViewModel and LiveData.
Example of a robust login dialog with a custom layout that perfectly preserves its state during configuration changes.
It also performs a slight validation of input data.
This part demonstrates the basic usage of the Room database framework.
Both lists within the Activity are being updated immediately and reactively.
Even the list that requests odd items only through the WHERE
condition.
Working with SQLite database has never been so pretty!
This example shows an approach to create a list with each item containing a CheckBox. CheckBox (like other Android components) isn't well suitable for the unidirectional data flow principle. It's actually not a big deal since we have the two-way data-binding feature, which is really convenient when the View is directly connected to a LiveData-field within the ViewModel. But things are getting quite confusing when we're building lists.
To make the example more informative I've added a couple of features:
- Total number of selected items.
- Delay between clicking CheckBox and the actual updating of the dataset (simulating a request or something).
This software is released under the MIT License. See LICENSE.txt for details.