Continuing from last article, we need to implement some mechanism for caching the quote offline so that whenever user will open the app, he will see last quote loaded without waiting to load new quote and in background we will request server for new quote and update the UI whenever data is available. We are going to use Room Persistence Library for that!
- Single source of Truth:
From Wikipedia, In Information systems design and theory, single source of truth (SSOT), is the practice of structuring information models and associated schemata such that every data element is stored exactly once. Suppose you will be using same quote at multiple places in your app, you don’t want this quote to come from REST endpoint at every place. Inconsistencies may occur in data if data is changed in between 2 REST calls. Because of this, in our case SSOT will be our DB. Response of REST API will alter the DB and all the parts of application will access the data from DB. LiveData will help notify all the active listener for changes in data!
You might have used SQLiteOpenHelper class for manually storing data in DB, if not you can learn how to do that here. But we are not going to use that approach here, we will be using Room Persistence Library for that. Why? because it will help us remove the boiler plate code and make our code look much cleaner. Who don’t want that?
- Room Persistence Library
There are 3 major components in Room1. Entity: This component represents a class that holds a database row. For each entity, a database table is created to hold the items. You must reference the entity class through the array
class. Each field of the entity is persisted in the database unless you annotate it with
@Ignore.2. Data Access Object (DAO): This component represents a class or interface as a Data Access Object (DAO). DAOs are the main component of Room and are responsible for defining the methods that access the database. The class that is annotated
mustcontain an abstract method that has 0 arguments and returns the class that is annotated with
.When generating the code at compile time, Room creates an implementation of this.3. Database: You can use this component to create a database holder. The annotation defines the list of entities, and the class’s content defines the list of data access objects (DAOs) in the database. It is also the main access point for the underlying connection .Youcan read more about Room here. If you did not understand the room components yet, don’t worry, code examples will make sure you understand it well .Withoutwasting much time, we will dive into codenow!
We have to create those 3 components mentioned above. We will make those step by step.
This class represent the row which we will be storing in our table. We want to store a quote in db as a row. So we are going to make little modification to our Quote class to make it as entity as shown below.
@Entity :When a class is annotated with
andis referenced in the
annotation, Room creates a database table for that entity in the database. By default, roomwill create columnfor each field in table. To store the fields in table, roommust have access to that field. You can either make the field public or provide public getter and setter for the field. @PrimaryKey: Each entity must define at least 1 field as a primary key. As we currently have only 1 quote to store in table, we will create onint field with constantvalue and make it as primarykey. It will make sure we have only 1 quote at a time in table!
We will create
DAOinterface for defining methods which will actually be used for data retrieval and data storage for our db.
@Dao: Marks the class as a Data Access Object. Data Access Objects are the main classes where you define your database interactions. They can include a variety of query methods. The class marked with
@Daoshould either be an interface or an abstract class. At compile time, Room will generate an implementation of this class when it is referenced by a
Database. @Insert: Marks a method in a
Daoannotated class as an insert method. @Update: Marks a method in a
Daoannotated class as an update method. @Query: The value of the annotation includes the query that will be run when this method is called. This query is verified at compile time by Room to ensure that it compiles fine against the database. As we have only 1 entry as of now in table, we are using the query “SELECT * FROM quote” to fetch the only record from table. Query is returning LiveData object, so whenever changes in data is made in db, all the observers will be notified of change and will update UI accordingly.
- @Database: Marks a class as a RoomDatabase. We have to mention entities along with this annotation. We have only 1 entity as of now which we have mentioned above along with the version number for db. Every time you make changes to db schema by changing fields in entity class (Quote.java), version number needs to be increased. Database class has only one method which will return instance of our DAO object which we will use to interact with actual db.
Now our all 2 components for Room are ready and we can modify QuoteRepository class to include offline caching feature of our app. Modified QuoteRepository class will look something like below.
As you can see, QuoteRepository is same as our previous implementation for the most part but with the minor change. Instead of returning data from web service call, we are returning data (Quote object) from db and making change to db via web service call in background. Whenever data in db will change, observers will be notified to make changes in UI.
As we cannot access db in main thread, we need to run the db access operations in new thread (Executor).
Now after implementing this much part, our app will open with quote already loaded on screen and web service call being done in background. We have skipped exposing network status i.e. showing user that data is being loaded in background. That is topic for all together different article. You can know more about it here.
If you are following your development of app with article, it looks pretty basic (kind which is developed by noobies), and kind of useless. So was I wasting your time this whole time? No, I will demonstrate you in next article, how we can easily transform this app into something beautiful. Next article is going to be a bit lengthy so make sure you dive in with a coffee.
I will be writing more articles about tips and tricks for making most of your android application in future, subscribe our newsletter for getting the articles directly in your inbox. Subscription box can be found on top right side of this article of you are on PC and at the bottom of this article if you are on mobile device.