User Tools

Site Tools


persist_data_with_room

Persist Data with Room

1. Before you begin

Room is a persistence library that's part of Android Jetpack. Room is an abstraction layer on top of a SQLite database. SQLite uses a specialized language (SQL) to perform database operations. Instead of using SQLite directly, Room simplifies the chores of database setup, configuration, and interactions with the app. Room also provides compile-time checks of SQLite statements.

…

2. App overview

…

3. Starter app overview

You can browse the code in the Inventory app GitHub repository.

  • ui/home/HomeScreen.kt
    • list of items
  • ui/item/ItemEntryScreen.kt
    • item details
  • ui/navigation/InventoryNavGraph.kt
    • navigation graph for the entire application

4. Main components of Room

  • Room entities represent tables in your app's database. You use them to update the data stored in rows in tables and to create new rows for insertion.
  • Room DAOs provide methods that your app uses to retrieve, update, insert, and delete data in the database.
  • Room Database class is the database class that provides your app with instances of the DAOs associated with that database.

5. Create an item Entity

  • An Entity class defines a table, and each instance of this class represents a row in the database table.
  • The @Entity annotation marks a class as a database Entity class.
  • Each field of the Entity is represented as a column in the database, unless denoted otherwise.
  • Data classes are primarily used to hold data in Kotlin. They are defined with the keyword data.
  • The @Entity annotation has several possible arguments. By default (no arguments to @Entity), the table name is the same as the class name. Use the tableName argument to customize the table name.
  • Annotate the id property with @PrimaryKey to make the id the primary key.
  • If you want to auto generate values set a default value of 0, which is necessary to auto generate values.
  • Add the autoGenerate parameter to the @PrimaryKey annotation to specify whether the primary key column should be auto-generated. If autoGenerate is set to true, Room will automatically generate a unique value for the primary key column when a new entity instance is inserted into the database.

6. Create the item DAO

  • The Data Access Object (DAO) is a pattern you can use to separate the persistence layer from the rest of the application by providing an abstract interface. This isolation follows the single-responsibility principle, which you have seen in previous codelabs.
  • The DAO you create is a custom interface that provides convenience methods for querying/retrieving, inserting, deleting, and updating the database. Room generates an implementation of this class at compile time. The Room library provides convenience annotations, for defining methods that perform SQL statements, e.g.:
    • @Insert
    • @Delete
    • @Update
    • @Query
    • …?
  • The argument onConflict tells the Room what to do in case of a conflict. The OnConflictStrategy.IGNORE strategy ignores a new item.
  • It is recommended to use Flow in the persistence layer. With Flow as the return type, you receive notification whenever the data in the database changes. The Room keeps this Flow updated for you, which means you only need to explicitly get the data once.
  • Because of the Flow return type, Room also runs the query on the background thread. You don't need to explicitly make it a suspend function and call it inside a coroutine scope.

7. Create a Database instance

  • The Database class provides your app with instances of the DAOs you define.
  • You need to create an abstract RoomDatabase class and annotate it with @Database. This class has one method that returns the existing instance of the RoomDatabase if the database doesn't exist.
  • Create a public abstract class that extends RoomDatabase. The new abstract class you define acts as a database holder. The class you define is abstract because Room creates the implementation for you.
  • Annotate the class with @Database. In the arguments, list the entities for the database and set the version number. The @Database annotation requires several arguments so that Room can build the database.
    • Specify the list of entities.
    • Set the version. Whenever you change the schema of the database table, you have to increase the version number.
    • Set exportSchema to false so as not to keep schema version history backups.
  • define a companion object, which allows access to the methods to create or get the database and uses the class name as the qualifier.
  • Inside the companion object, declare a private nullable variable Instance for the database and initialize it to null.
  • Annotate Instance with @Volatile.
    • The value of a volatile variable is never cached, and all reads and writes are to and from the main memory. These features help ensure the value of Instance is always up to date and is the same for all execution threads. It means that changes made by one thread to Instance are immediately visible to all other threads.
  • Below Instance, while still inside the companion object, define a getDatabase() method with a Context parameter that the database builder needs.
  • …

“Template code” for future projects:

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
 
/**
* Database class with a singleton Instance object.
*/
@Database(entities = [Item::class], version = 1, exportSchema = false)
abstract class InventoryDatabase : RoomDatabase() {
 
    abstract fun itemDao(): ItemDao
 
    companion object {
        @Volatile
        private var Instance: InventoryDatabase? = null
 
        fun getDatabase(context: Context): InventoryDatabase {
            // if the Instance is not null, return it, otherwise create a new database instance.
            return Instance ?: synchronized(this) {
                Room.databaseBuilder(context, InventoryDatabase::class.java, "item_database")
                    .build()
                    .also { Instance = it }
            }
        }
    }
}

8. Implement the Repository

…

9. Add the save functionality

…

View the database content using Database Inspector

Get the solution code

Summary

Learn more

persist_data_with_room.txt · Last modified: by kalaschnikow