Android Room Database — Complete Guide
In this tutorial, you'll learn about Android Room Database. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
The Problem
You create a new RoomDatabase instance on every screen, forget to run migrations, or your database class crashes because entities are missing.
Wrong Approach ❌
// No singleton pattern — multiple database instances
class MyActivity : AppCompatActivity() {
fun onCreate() {
val db = Room.databaseBuilder(
this,
AppDatabase::class.java, "my-db"
).build() // New instance every time!
}
}
@Database(entities = [User::class], version = 2) // Version bumped
abstract class AppDatabase : RoomDatabase() {
// No migration from version 1 to 2
}
Output: IllegalStateException: A Migration from 1 to 2 is required.
Right Approach ✅
@Database(
entities = [User::class, Order::class],
version = 2,
exportSchema = true
)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
companion object {
@Volatile
private var INSTANCE: AppDatabase? = null
fun getInstance(context: Context): AppDatabase {
return INSTANCE ?: synchronized(this) {
INSTANCE ?: Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java, "my-db"
).addMigrations(MIGRATION_1_2).build().also {
INSTANCE = it
}
}
}
private val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL("ALTER TABLE users ADD COLUMN avatar_url TEXT")
}
}
}
}
Output: Thread-safe Singleton database with proper migrations.
Prevention
- Always implement the Singleton Pattern for
RoomDatabase. - Use
Context.applicationContextto avoid memory leaks. - Write explicit
Migrationclasses for every version change. - Set
exportSchema = trueand check in the generated JSON for schema reviews.
Common Mistakes with room database
- Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors
- Non-exhaustive pattern matches that compile with warnings then crash at runtime
- Misunderstanding that
Stringis[Char]with poor performance for large text operations
These mistakes appear frequently in real-world ANDROID code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro