Local Persistence with Room
Room is Android's official persistence library — a type-safe, compile-time-checked layer over SQLite that turns annotated Kotlin classes into a real relational database without the boilerplate.
Learn Local Persistence with Room in our free Kotlin course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…
Part of the free Kotlin course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
By the end you'll define an @Entity , write a reactive @Dao , and wire up a RoomDatabase .
What You'll Learn in This Lesson
1️⃣ Defining a Table with @Entity
An @Entity turns a data class into a table: each instance is a row, each property a column. Mark one property with @PrimaryKey , optionally with autoGenerate = true so Room assigns IDs.
Room reads these annotations at compile time and generates the matching SQLite schema for you.
2️⃣ Querying with a @Dao
A @Dao interface declares your data access. Use @Query for custom SQL, plus @Insert / @Update / @Delete . Return a Flow for reactive reads, and mark writes suspend .
Because observeAll() returns a Flow , your UI refreshes itself whenever the data changes — no polling required.
3️⃣ The @Database Class
The @Database class extends RoomDatabase , lists every entity and a version, and exposes abstract DAO getters. Build a single instance with Room.databaseBuilder .
Model a Task entity, a reactive DAO, and a database that exposes it.
📋 Quick Reference — Room
Practice quiz
What annotation marks a class as a Room database table?
- @Entity
- @Model
- @Persist
- @Table
Answer: @Entity. @Entity marks a data class as a table; each instance is a row and each property a column.
Which library does Room sit on top of?
- Realm
- A custom NoSQL engine
- SQLite
- Firebase
Answer: SQLite. Room is an abstraction layer over Android's built-in SQLite, removing boilerplate while keeping full SQL access.
What annotation marks an interface that defines database access methods?
- @Repository
- @Dao
- @Access
- @Query
Answer: @Dao. A Data Access Object (@Dao) declares the methods used to read and write data.
Which annotation lets you write a custom SELECT statement in a DAO?
- @Sql
- @Select
- @Fetch
- @Query
Answer: @Query. @Query holds an arbitrary SQL statement; Room validates it at compile time.
How do you define the primary key for an entity?
- With @PrimaryKey on a property
- By naming a property 'id'
- Room picks one automatically with no annotation
- With the @Key annotation on the class
Answer: With @PrimaryKey on a property. @PrimaryKey marks the property; add autoGenerate = true to let Room assign incrementing IDs.
Why return a Flow from a Room @Query?
- It encrypts the rows
- It makes the query observable, re-emitting when the underlying data changes
- It runs the query on the main thread
- It compresses the result
Answer: It makes the query observable, re-emitting when the underlying data changes. A Flow-returning query is reactive: Room re-emits a fresh result whenever the table's data changes.
Why should insert/update/delete DAO methods usually be 'suspend' functions?
- Because Room requires it for compilation
- To make them faster than SQL
- So they return a Flow automatically
- So they run off the main thread without blocking the UI
Answer: So they run off the main thread without blocking the UI. Marking write methods suspend lets you call them from coroutines so disk I/O never blocks the UI thread.
What class must your database class extend, annotated with @Database?
- DatabaseHelper
- ContentProvider
- RoomDatabase
- SQLiteOpenHelper
Answer: RoomDatabase. The @Database-annotated abstract class extends RoomDatabase and exposes abstract DAO getters.
What is a Room migration used for?
- Moving the app to a new device
- Defining how to upgrade the schema from one version to the next
- Copying data to the cloud
- Switching from SQLite to MySQL
Answer: Defining how to upgrade the schema from one version to the next. A Migration tells Room the SQL needed to evolve the schema when the database version increases, preserving user data.
What does a @TypeConverter let Room do?
- Store a custom type (like Date) by converting it to and from a type SQLite supports
- Convert Kotlin to Java
- Encrypt a column
- Convert between SQL dialects
Answer: Store a custom type (like Date) by converting it to and from a type SQLite supports. A @TypeConverter maps an unsupported type (such as Date or an enum) to a primitive SQLite can store, and back.