A clean installation only proves the new schema can be created. Existing users need a path from their stored schema to the new one that preserves the meaning of their data.
Suppose LessonProgress already has an id primary key and a completion column. Adding a non-null bookmark flag requires a value for old rows.
This migration fragment assumes version 4 introduces isBookmarked:
val MIGRATION_3_4 = object : Migration(3, 4) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL(
"ALTER TABLE LessonProgress " +
"ADD COLUMN isBookmarked INTEGER NOT NULL DEFAULT 0"
)
}
}
Declare a matching database default in the entity, such as @ColumnInfo(defaultValue = "0"), update the database version, and register the migration. This snippet assumes a Room configuration using the corresponding support SQLite APIs.
Use exported schemas and MigrationTestHelper to create an older database, insert completed and incomplete lessons, migrate, and verify both schema and values. Test upgrade paths for users who skip releases, plus a fresh installation.
Why not enable destructive fallback? Dropping and recreating tables can erase the only copy of learning progress. It may suit disposable caches, but it must be an explicit data-loss decision rather than a way to silence migration failures.
Mark this when you can explain the answer in your own words.
Help fellow developers prepare for interviews
Sharing helps the Android community grow ๐