SuperAPI AI Directory

android-room

Coding & development

View repository

Updated 10-15 20:31

About this skill

Room and DataStore

Room is the structured local source. DataStore is preferences/proto — not a second SQLite. App: android-development. Streams: kotlin-coroutines. JVM tests: android-unit-testing.

Stack and scope

Item Role
Room SQLite, DAOs, migrations
KSP Annotation processing
DataStore Preferences or Proto
SQLCipher Only if the product requires encryption

Do not introduce Realm/ObjectBox into a feature if Room is already in the app.

Organization

data/local/
  db/
    AppDatabase.kt
    entities/
    daos/
    converters/
    migrations/
  datastore/
    UserPrefs.kt
  • One AppDatabase. DAOs per aggregate.
  • Repository combines Room + network; UI does not call DAO.

Non-negotiable rules (Room)

  • exportSchema = true and schema in git. Migrations tested.
  • Never destructive fallbackToDestructiveMigration() in production.
  • Queries in the DAO; no SQL concatenated with input.
  • Flow / PagingSource for observation. suspend for writes.
  • Main thread: allowMainThreadQueries forbidden in prod.
  • Version + migration for every schema change.
@Dao
interface OrderDao {
    @Query("SELECT * FROM orders WHERE id = :id")
    fun observe(id: String): Flow<OrderEntity?>

    @Upsert
    suspend fun upsert(order: OrderEntity)
}

Modeling

  • Entities ≠ UI models. Map in the data layer.
  • @Embedded / @Relation aware (relation N+1).
  • Indexes and unique aligned with real queries.
  • TypeConverters for enums/instant; not for opaque JSON graphs without need.
  • Foreign keys with explicit onDelete .

Migrations

val MIGRATION_2_3 = object : Migration(2, 3) {
    override fun migrate(db: SupportSQLiteDatabase) {
        db.execSQL("ALTER TABLE orders ADD COLUMN notes TEXT")
    }
}
  • MigrationTestHelper in JVM tests.
  • New columns nullable or with default. Backfill in migration if needed.
  • AutoMigration only when the diff is trivial and reviewed.

DataStore

  • Typed keys; one file per context (settings, session).
  • edit { } atomic. No SharedPreferences new.
  • Proto DataStore for versioned schemas; Preferences for simple flags.
  • Do not put large lists / business blobs in DataStore — use Room.
  • Read with Flow; first() only on one-off boot.

Concurrency and quality

  • Writes serialized on the Room executor. Do not open multiple AppDatabase.
  • Tests: Room.inMemoryDatabaseBuilder + InstantTaskExecutor / runTest.
  • Paging 3 for infinite lists.

Anti-patterns

  • getAll() in the onCreate of the Activity
  • Entity in Compose UI
  • Destructive migration “just this once”
  • DataStore as feed cache
  • Gson converter for a giant object in a column

Integration with other skills

  • App: android-development
  • Flow: kotlin-coroutines
  • Tests: android-unit-testing
  • Offline + network: single repository, not two sources in the UI

Completion criteria

  • DAO + Flow; no SQL in the UI
  • Versioned and tested migration if the schema changed
  • Exported schema
  • Prefs in the DataStore, not the new SP
  • No queries in Main