Room-Datenbank in Kotlin – Entity, DAO und Database in unter 30 Zeilen
Daten lokal auf dem Gerät speichern, ohne selbst SQL-Strings zusammenzubauen: Room ist die empfohlene Persistenz-Bibliothek für Android. Die drei Bausteine – Entity, DAO und Database – und wie sie zusammenspielen.
Sobald deine App Daten behalten soll, die einen Neustart überleben – Notizen, ein Warenkorb, ein Cache – brauchst du eine lokale Datenbank. Auf Android ist Room dafür der empfohlene Weg: eine Abstraktionsschicht über SQLite, die dir das Zusammenbauen von SQL-Strings abnimmt und Fehler schon zur Compile-Zeit findet. Room besteht aus genau drei Bausteinen.
1. Entity – die Tabelle
Eine data class mit @Entity beschreibt eine Tabelle, jedes Feld ist eine Spalte:
@Entity(tableName = "notes")
data class Note(
@PrimaryKey(autoGenerate = true) val id: Long = 0,
val title: String,
val createdAt: Long,
)2. DAO – die Zugriffe
Das Data Access Object ist ein Interface mit deinen Abfragen. Room generiert die Implementierung:
@Dao
interface NoteDao {
@Query("SELECT * FROM notes ORDER BY createdAt DESC")
fun observeAll(): Flow<List<Note>> // liefert bei jeder Änderung neu
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun upsert(note: Note)
@Delete
suspend fun delete(note: Note)
}3. Database – die Klammer
Eine abstrakte Klasse verbindet Entities und DAOs:
@Database(entities = [Note::class], version = 1)
abstract class AppDb : RoomDatabase() {
abstract fun noteDao(): NoteDao
}
// Einmal bauen (am besten über Dependency Injection als Singleton):
val db = Room.databaseBuilder(context, AppDb::class.java, "app.db").build()
val dao = db.noteDao()Warum das im Alltag angenehm ist
- Main-sicher von Haus aus.
suspend-Funktionen undFlow-Abfragen wechseln intern selbst den Thread – du musst Datenbankzugriffe nicht mehr von Hand inwithContext(Dispatchers.IO)wickeln. - Reaktiv mit Flow. Gibt ein DAO einen
Flowzurück, bekommt dein UI bei jeder Änderung automatisch die neue Liste. In Compose liest du das mitcollectAsStateWithLifecycle(). - Fehler früh. Room prüft deine
@Query-Strings beim Kompilieren gegen das Schema – ein Tippfehler im SQL fällt sofort auf, nicht erst beim Nutzer. - Migrationen nicht vergessen. Änderst du das Schema, musst du
versionerhöhen und eine Migration angeben (oder in der EntwicklungfallbackToDestructiveMigration()nutzen – aber niemals in Produktion, das löscht die Daten).
Wenn du eine Android-App brauchst, die Daten sauber und offline-fähig speichert, sprich mich an.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
Einstellungen speichern mit DataStore – der moderne Ersatz für SharedPreferences
SharedPreferences ist alt, blockiert den Main-Thread und kennt keine Coroutinen. DataStore macht dasselbe – nur asynchron, typsicher und als Flow. So speicherst du Nutzer-Einstellungen richtig.
Parallele Netzwerkaufrufe mit async/await – zwei Requests, halbe Wartezeit
Wenn ein Screen zwei unabhängige Daten braucht, musst du nicht erst auf den einen und dann auf den anderen Request warten. Mit async und coroutineScope laufen sie parallel – strukturiert und sicher.
DisposableEffect in Compose – aufräumen, wenn ein Composable verschwindet
Immer wenn du in Compose etwas registrierst – einen Listener, einen Sensor, einen Callback – musst du es auch wieder abmelden. Genau dafür gibt es DisposableEffect mit seinem onDispose-Block.