Introduction to Room Persistent Library in Android
Welcome to the Advanced Room series which covers all the details about Room Persistent Library. In this series, we will start with the basics of Room, then we will learn how to use it. We will learn about the various components of Room in detail and we will also learn how to use Room with LiveData and other third-party libraries like RxJava and Kotlin coroutines. Here is the list of the blogs in this series:
- Introduction to Room Persistent Library in Android [You are here]
- Data Access Objects — DAO in Room
- Entity Relationship in Room
- How does Room work internally?
- Room Database Migrations
- Using Room with LiveData and other third-party libraries
Room Introduction
This part covers the basics of Room persistence library. After reading this, you can start using Room in your android applications.
Room is an Android persistence library that is part of Google’s Android Jetpack project. According to the documentation, Room provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite.
Apps that handle significant amounts of structured data can benefit greatly from persisting that data locally. The most common use case is to cache relevant pieces of data. That way, when the device cannot access the network, the user can still browse that content while they are offline. Any user-initiated content changes are then synced to the server after the device is back online.
Adding Room in your project
Add the following in your module’s(app) build.gradle
file:
dependencies {
implementation "androidx.room:room-runtime:2.2.5"
kapt "androidx.room:room-compiler:2.2.5"
}
Advantages of using Room
There are multiple advantages of using Room as compared to other alternative solutions like SQLiteOpenHelper:
- Compile-time verification of queries.
- Reduces boilerplate code.
- Easy to understand and use.
- Easy integration with RxJava, LiveData, and Kotlin Coroutines.
Components of Room
There are 3 major components in Room:
- Database: Contains the database holder and serves as the main access point for the underlying connection to your app’s persisted, relational data.
- Entity: Represents a table within the database.
- DAO: Contains the methods used for accessing the database.
Your application uses the Room database to get the data access objects, or DAOs, associated with your database. The app then uses each DAO to get entities from the database and save any changes to those entities back to the database. Finally, the app uses an entity to get and set values that correspond to table columns within the database.
Database
As mentioned earlier, it contains the database holder and serves as the main access point for the underlying connection to your app’s persisted, relational data. The class that’s annotated with @Database
should satisfy the following conditions:
- Be an abstract class that extends
RoomDatabase
. - Include the list of entities associated with the database within the annotation.
- Contain an abstract method that has 0 arguments and returns the class that is annotated with @Dao
- At runtime, you can acquire an instance of
Database
by callingRoom.databaseBuilder()
orRoom.inMemoryDatabaseBuilder()
To get an instance of the database, you can use the following method:
Note: If your app runs in a single process, you should follow the singleton design pattern when instantiating a
RoomDatabase
object. EachRoomDatabase
instance is fairly expensive, and you rarely need access to multiple instances within a single process.
Entity
Entity represents a table within a database. This class is annotated with @Entity annotation. Data members in this class represent the columns within a table.
- All the fields in an entity must either be public or have getter & setter methods.
- Entity class should have an empty constructor (if all fields are accessible) or a parameterized constructor which takes all the fields. Room can also use partial constructors.
- Each entity class must have atleast one primary key. You can use either @PrimaryKey annotation to define single field primary key or
primaryKeys
attribute of @Entity annotation for multiple fields. You can also useautoGenerate
property of @PrimaryKey annotation to automatically assign primary keys.
@Entity(primaryKeys = arrayOf("firstName", "lastName"))
- By default, Room uses the class name as the database table name. If you want the table to have a different name, set the
tableName
property of the@Entity
annotation. Similarly, you can use the name property of the@ColumnInfo
annotation for defining the name of columns.
@Entity(tableName = "users")
- If you don’t want to persist any field, you can annotate them using
@Ignore.
@Ignore val picture: Bitmap?
- You can use the indices property of @Entity annotation to add indices to an entity. Also, you can create unique indices by setting the
unique
property of an@Index
annotation totrue
.
@Entity(indices = arrayOf(Index(value = ["last_name", "address"])))@Entity(indices = arrayOf(Index(value = ["first_name", "last_name"],
unique = true)))
Data Access Object (DAO)
DAOs provide an api for accessing the database. This is an interface which is annotated with @Dao annotation. All the methods in this interface are used for getting data from the database or making changes to the database. These methods are annotated with annotations like @Query, @Insert, @Delete.
Note: All queries using UserDao are made on the caller thread. So you should take care that no method is invoked from the UI(main) thread.
Type Converters
Sometimes, you might need to persist a custom data type in a single database column. You can use type converters for these types of use cases.
Next, you have to add the @TypeConverters
annotation to the RoomDatabase
class so that Room can use the converter that you've defined for each entity and DAO in that RoomDatabase.
Thank You !!!