Android Architecture Components — Room, LiveData and ViewModel
During the concluded Google I/O 2017, there were some amazing announcements about Android. Say hello to Android Architecture Components. For once, these are announcements that ease our lives as Android Developers.
Android Architecture Components
A new collection of libraries that help you design robust, testable, and maintainable apps. — developer.android.com
It helps us developers address two pain points:
- Manage our UI components lifecycle
- Persist data over configuration changes
In fact, these are the two biggest problems we Android Developers face. Period.
Maintaining data over orientation changes and handling our objects with lifecycle is hard. That’s why, to avoid the hassle, you lock your apps in Portrait mode, don’t you? Don’t lie. Even I’ve done it.
But don’t worry, Android Architecture Components will help alleviate both our fears.
We will see 3 main components :
So first, let’s find out what these components actually are. Then, we’ll learn how we can use them.
We’ll even make a handy app that keeps track of what people borrow. This will help us learn better about how all these 3 components work together.
Remember the amount of boilerplate code you had to write to create and manipulate even a very small database? You had to define the database structure, create an SQLiteHelper class etc.
Room is a library that saves you all such trouble. Now you can query your data without having to deal with cursors or loaders. You can define your database by adding annotations in your Model class. Yes, it’s that simple.
If you’ve used third-party ORMs like Sugar, you’ll feel right at home here. In fact, from now on, I wouldn’t even want to use one. Room is that brilliant! Why would you want to use a third-party library, when the official Android libraries give you an equal, or if not, better solution.
In this app, we will follow an architecture called MVVM — Model View ViewModel.
In MVVM, the
ViewModelexposes the required data and interested parties can listen to it.
But you don’t have to worry. We’ll do a simple implementation for this article. You’ll have no problem following.
So in our case, the
Activity will listen on the data and make changes in the UI.
Create a new project in Android Studio.
First, Add Google’s maven repository to your project-level build.gradle file.
Next, add the following dependencies for Architecture Components and Room in your app-level build.gradle file.
Creating the Model
We will call our model BorrowModel.
You might see an error at DateConverter.class. But don’t panic, we’ll create that next. So for now, pay attention to the Annotations used here.
We use the
@Entity annotation to tell Room to use the current class as a database table.
Any attribute preceded by the
@PrimaryKey annotation will serve as a primary key for the table. Here we use
'autoGenerate = true' so that the key is automatically generated every time an entry is made.
SQL cannot store data types like
Date by default. That’s why we need a way to convert it into a compatible data type to store it in the database. We use the
@TypeConverters to specify the converter for the
borrowDate attribute. So to help us with this conversion, we’ll create a class called DateConverter.
As you can see, the class just converts
Long and vice versa.
Data Access Object
Next up, we need to create a DAO — Data Access Object class. This class will be used to define all the queries we will perform on our database.
@Dao to tell Room that this is a DAO class.
We define our queries as strings and pass them as a parameter to
@Query annotation is paired with a method. When the paired method is called, the query gets executed.
Next, we use the
@Insert annotation for methods that insert entries into the table. We can similarly use
@Update for deletion and update method respectively.
In case there are conflicts during such manipulation operations, we have to specify a conflict strategy too. In our example, we are using REPLACE. It means that the conflicting entry will be replaced by the current entry.
Make sure you import REPLACE correctly using
import static android.arch.persistence.room.OnConflictStrategy.REPLACE;
Creating the database
Now, all we need to do is create a RoomDatabase class. So create an abstract class called AppDatabase.
We annotate the class with
@Database which takes two arguments:
- An array of the Entity classes(the tables)
- The database version which is just an integer.
This class is used to create the database and get an instance of it. We create the database using
Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "borrow_db")
The arguments are:
- Your database class
- Name to given to the database
We have to create an abstract method for every DAO class that we create. This is really important.
And that’s it. Our database is ready to roll.
Earlier in the post, we mentioned
ViewModel. ViewModels are entities that are free of the
Fragment lifecycle. For example, they can retain their state/data even during an orientation change.
ViewModels do not contain code related to the UI. This helps in the decoupling of our app components.
Room, the database instance should ideally be contained in a ViewModel rather than on the
Create the AndroidViewModel
We create a ViewModel for our borrowed items.
Every ViewModel class must extend the
ViewModel class. If your ViewModel needs the application context, it must extend
AndroidViewModel. The ViewModel will contain all the data needed for our
Activity. In our example, we are using something called LiveData.
LiveData is a wrapper that lets interested classes observe changes in the data inside the wrapper.
We wrap our list of borrowed items inside LiveData so that the
Activity can observe changes in the data and update the UI.
In our ViewModel, we first get an instance of our database using
First, we need to load the list of borrowed items from the database. For that, we should use the query we defined in the DAO class,
Next, call the abstract method we created for DAO and then call the query method. Refer to this snippet in the
Now since we will be displaying a list of items, we need a
RecyclerView. So first, let’s create an adapter for the same.
Creating the Android LifecycleActivity
It’s a pretty straightforward adapter. So I won’t be getting into the details of it. But if you’re interested in how
RecyclerView works, this Android tutorial tells you how to create a
Now create an
Activity that extends
LifecycleActivity to display a list of all the borrowed items.
LifecycleActivityis a class that provides us with the state of the lifecycle.
EDIT: We no longer need to extend LifecycleActivity explicitly. The required methods are available in AppCompatActivity.
Whenever we need to use ViewModels inside our
Activity must extend
Creating a ViewModel is simple.
viewModel = ViewModelProviders.of(this).get(BorrowedListViewModel.class);
The two parameters are:
- The ViewModel class
Now we need to make our
Activity observe the changes in the ViewModel. So first, get a reference to the LiveData inside the ViewModel. Then, add an
observe() method to the reference.
observe() method takes 2 parameters:
- The owner of the Lifecycle. In our case, it is the
Whenever there is a change in the data, the
onChanged() callback is executed and we get the new data. We can update the UI accordingly.
Simple Exercise — Create the ‘Add Item Screen’
Now we have an
Activity that can display a list of borrowed items. But how do we add items to the database?
It’s simple. You need to create an AddItemActivity.
The entire procedure is exactly the same as before. But in this case, you need to call the
addBorrow() DAO method and pass a
Borrow object as a parameter. And that is it. Our app is ready.
I encourage you to try this screen on your own. But in case you get stuck, you can refer to my files on GitHub.
So go ahead and run your app. You should get an output similar to this.
The Android Architecture Components give us great advantage and relief. Hence, we don’t have to worry about
- lifecycle changes
- memory leaks
- data retention across configuration changes
If you recount, these are the biggest challenges faced by even veteran Android developers.
As always, the code from the post can be found on GitHub.
In the post, we got introduced to Android Architecture Components. Then, we learnt about Room and used it to create databases in a fast and easy way. Next, we also learnt how to make our UI respond to changes in data. Also, by using
ViewModels, we did not have to use a lot of callbacks.
Additionally, we even learnt a bit about the MVVM architecture.
We have barely scratched the surface in terms of what’s possible with these new components. So I hope to discover more as I continue to tinker with Android Architecture Components.
So are you going to use these components? Would you consider
Room in any of your apps? Or maybe ViewModels to simplify your code? I’d love to hear your comments.
Special shout out to Suleiman Ali Shakir for always helping me out and making amazing edits and Raghav Sai for correcting the endless derps.gi
First published at blog.iamsuleiman.com on May 23, 2017.