The Room cache — Entity, DAO, Database
Three files in the code column as tabs, in dependency order: MenuItemEntity.kt → MenuDao.kt → PicaDatabase.kt (a row, then how you read/write it, then the database that holds it).
1. MenuItemEntity.kt — the cache row. It's separate from the domain MenuItem (lesson 2): the entity lives in core/data/local (the storage layer), carries @Entity and @PrimaryKey, while MenuItem stays the clean model the UI renders. We map between them.
First add the Room dependencies in build.gradle.kts (stack-when-needed; Room 2.x, not 3.0):
implementation(libs.androidx.room.runtime)
implementation(libs.androidx.room.ktx) // Flow + suspend support
ksp(libs.androidx.room.compiler) // plugin: id("androidx.room") + id("com.google.devtools.ksp")
2. MenuDao.kt — how you read and write. The key asymmetry: reads return a Flow (a live stream — the UI re-renders when the table changes), writes are suspend (insertAll, clearAll).
3. PicaDatabase.kt — the database itself: @Database(entities = [MenuItemEntity::class], version = 1), exposing menuDao().
Gotcha (schema migration).
version = 1matters. If you later change the entity (add a column) and don't bump the version, Room throws anIllegalStateExceptionabout a schema mismatch. And if you bump the version (version = 2) without a migration you get:java.lang.IllegalStateException: A migration from 1 to 2 was required but not found.Fixes: write a
Migration(1, 2)(preserves data), or — for a cache —.fallbackToDestructiveMigration()(drops and rebuilds; fine for a cache, since the server is the source of truth). Never just bump the version "to make it compile."