Coroutines for Asynchronous Programming
# Chapter 19: Local Databases with Room
<div class="toc"> <ul> <li><a href="#introduction">1. Introduction</a></li> <li><a href="#what-is-room">2. What is Room?</a></li> <li><a href="#setup">3. Adding Room to Your Project</a></li> <li><a href="#room-components">4. The Three Components of Room</a></li> <li><a href="#implementation">5. Step-by-Step Implementation</a></li> <li><a href="#using-room">6. Using the Database</a></li> <li><a href="#exercises">7. Exercises & Challenges</a></li> <li><a href="#quiz">8. Quiz</a></li> <li><a href="#interview-questions">9. Interview Questions</a></li> </ul> </div>
<h2 id="introduction">1. Introduction</h2> For storing complex, structured data locally (like a list of tasks, cached news articles, or user profiles), SharedPreferences is not enough. Android devices have a built-in relational database system called SQLite. However, using standard SQLite requires writing lots of boilerplate SQL code and manual data mapping.
<h2 id="what-is-room">2. What is Room?</h2> Room is a Jetpack Architecture Component that acts as an abstraction layer over SQLite. It maps your Kotlin objects directly to database tables (an ORM - Object Relational Mapper) and provides compile-time checks for your SQL queries, preventing app crashes from typos in SQL strings.
<h2 id="setup">3. Adding Room to Your Project</h2>
Add the following dependencies to your app/build.gradle.kts file:
<h2 id="room-components">4. The Three Components of Room</h2> Room relies on three main annotations to generate the database code:
- 1. @Entity: Represents a table within the database.
- 2. @Dao: (Data Access Object) Contains the methods used for accessing the database (Insert, Update, Delete, Query).
- 3. @Database: The main access point for the underlying connection to your SQLite database.
<h2 id="implementation">5. Step-by-Step Implementation</h2>
Step 1: Create the Entity (Table)
Create a Kotlin data class and annotate it with@Entity.
Step 2: Create the DAO (Queries)
Create an Interface and annotate it with@Dao. Define your database operations here.
Step 3: Create the Database
Create an abstract class extendingRoomDatabase. It must be annotated with @Database.
*Note: The companion object implements the Singleton pattern, ensuring only one instance of the database is created, preventing memory leaks.*
<h2 id="using-room">6. Using the Database</h2> Database operations cannot be run on the Main (UI) thread, as they might take a long time and freeze the app. You must use Coroutines (or background threads).
<h2 id="exercises">7. Exercises & Challenges</h2> Challenge: Create a simple "Note taking" app.
-
1.
Create a
Noteentity withid,title, andcontent.
-
2.
Create a
NoteDaowith insert, update, delete, and read-all operations.
- 3. Build the Database class.
- 4. From your Activity, insert a dummy note and print all notes to the Logcat.
<h2 id="quiz">8. Quiz</h2> Q1: What does the @Entity annotation do in Room? a) Validates the database version. b) Defines the interface for SQL queries. c) Marks a data class to be created as a database table. d) Executes database operations asynchronously. Answer: c
Q2: Which Room component handles writing the actual SQL queries (like SELECT * FROM...)? a) Repository b) Entity c) Database d) DAO Answer: d
Q3: Why must database operations be run off the main thread? a) Because Room requires Coroutines to compile. b) Because disk I/O operations can freeze the UI and cause ANR (Application Not Responding) errors. c) Because the database is locked on the main thread. d) It's just a convention, they run fine on the main thread. Answer: b
<h2 id="interview-questions">9. Interview Questions</h2> Q: What are the main advantages of using Room over standard SQLiteOpenHelper? A: Room provides compile-time verification of SQL queries, reducing runtime crashes. It abstracts away the heavy boilerplate of mapping cursors to Java/Kotlin objects via an ORM mechanism, and it integrates seamlessly with modern Android architecture components like LiveData, Flow, and Coroutines.
Q: Why do we use the Singleton pattern for the Room Database instance? A: Creating a database connection is an expensive operation. If multiple instances are created, it consumes significant memory and can lead to database locking or concurrency issues. The Singleton pattern ensures only one connection exists throughout the app's lifecycle.