Android Architecture Components: Room, ViewModel and LiveData
A long time ago, when Android Developers develop apps with some of the core components like Activity, BroadcastReceiver, Services and Content Provider, with lots of hassle in making things work out. All developers are defeating Megatron all alone. But no more, our Android Optimus Prime is back with new powers called Architecture Components.
Why we need these new set of powers?
Let’s say about managing lifecycle, we have to manage the data, orientations or memory leaks all based on lifecycle and we have to do it on our own which is cumbersome sometimes. So, we need these new set of libraries which can do most of our work very easily without going into deep.
In this article, we will be focusing on a subset of these components. We are going to develop an app, which basically takes some input from the user(LiveData), save into the local database(Room) and show it on the screen(ViewModel). Let’s get started!!
1. Add Dependencies
We need to add Room and Lifecycle components. Room is basically a Database object mapping library use to access the database. Lifecycle, this has some good set of classes like ViewModel and LiveData which we will use to manage the lifecycle of our app.
Add these libraries to build.gradle (Module: app) file, at the end of the dependencies block.
2. Setup Room
First, the terminologies; there are 3 major annotations for using room:
Representation of table and columns becomes very easy, you just have to annotate “@Entity” to a class and name of the class becomes table name and, data members becomes the name of the columns. “@Entity” class represent an entity in a table.
Here, we have class Habit, and the name of the table is habitClass. We had made a single column habit, and for that, we used “@ColumnInfo” annotation and also made this a primary key by annotating “@PrimaryKey” to it.
b. “@Dao” — Data Access Object
An Interface where we put all our SQL queries. We don’t require to write whole queries now, we just need to make a method and annotate with specific annotations like “@Insert”, “@Delete”, “@Query(SELECT FROM *)”
Here, we have an interface HabitDao and some methods which we will call to perform our queries. To insert the data we annotated “@Insert” to insert method. Room doesn’t give us annotations which can help us in deleting everything so we have “@Query” to do some custom queries.
We need to create an abstract class (Room class) which extends RoomDatabase. It is a database layer over the SQLite database; this helps us in all the work which we use to do in SQLiteOpenHelper class. Room helps us with the compile-time checking of SQL statements; we need only a single instance for the whole app.
Here, we have a Room class HabitRoomDatabase in which we had to declare all our entities and version of the database. getDatabase() method will return the room database instance. If you want to modify the database do have a look at Migration.
3. Welcome LiveData
LiveData class is from lifecycle library, for observing the data changes. It’s an observable data holder class, and it is also lifecycle aware which means that this is going to update the component which is in the active lifecycle state.
fun getAllHabits() : LiveData<List<Habit>>
Here, in our project, where we are getting the list of habits, we are wrapping the list with LiveData.
4. Creating a Repository Class/Presentation Layer
This doesn’t come under the architecture component. This is a class where we will check whether to fetch data from API or local database, or you can say we are putting the logic of database fetching in this class.
Here, we added wrapper for getAllHabits() and insert(). Room run its operations on non-UI thread/background thread, so we used AsyncTask.
5. Here come’s the ViewModel
This is also the part of lifecycle library; this will help you to provide data between repository and UI. This survives the data on configuration changes and gets the existing ViewModel to reconnect with the new instance of the owner.
This is the lifecycle of ViewModel attached to an activity. Activity created and destroyed many times, but ViewModel survives the data. ViewModel is not the replacement of onSavedInstance because does not survive process shutdown although onSavedInstance can restore small data and ViewModel can restore a large amount of data like bitmaps.
Here, we are using AndroidViewModel because we need an application context. We created insert wrapper which will use the repository’s insert method.
6. Time to add RecyclerView
Create a layout file, we have a TextView in a row and also create a file which consists of RecyclerView. We need an adapter class which is responsible to show our data on the screen.
Here, we also checked if the list is empty than to display a proper message to the user.
7. Filling the Database
Here we had populated the data whenever the app starts and before that we also deleted existing data. We had a PopulateDbAsync which is an AsyncTask use to delete and insert the data.
8. Connect UI and Data
To display the data from the database, we need an observer who will observe the data changes, LiveData in the ViewModel. We have ViewModelProvider which is going to create a ViewModel for us. We need to connect our ViewModel with the ViewModelProvider, and then in the onChanged method, we always get our updated data which we can display on the screen.
Here, In MainActivity we had a fab button to open another activity where we can enter the data, and we had created onActivityResult method where we are getting the data which user had entered and inserted into the database.
9. Second Activity
We need an activity where the user can input the data. Here, we had an EditText and Button to submit the string.
That’s all! 😅 Run your app and experiment more around it.
Android-Udacity-Project-in-Kotlin - This repository contains the Android Basic Developer Nanodegree projects in kotlin
Update of this article will be coming soon with all the new AndroidX, Kotlin and Coroutine stuff.