Daten mit Room in einer lokalen Datenbank speichern Teil von Android Jetpack.
Apps, die nicht unerhebliche Mengen strukturierter Daten verarbeiten, können von der lokalen Speicherung dieser Daten profitieren. Der häufigste Anwendungsfall ist das Speichern relevanter Daten im Cache, damit Nutzer diese Inhalte auch dann aufrufen können, wenn das Gerät keinen Zugriff auf das Netzwerk hat.
Die Room-Persistenzbibliothek bietet eine Abstraktionsebene über SQLite, um einen flüssigen Datenbankzugriff zu ermöglichen und gleichzeitig die volle Leistung von SQLite zu nutzen. Room bietet insbesondere die folgenden Vorteile:
- Überprüfung von SQL-Abfragen zur Kompilierzeit
- Praktische Annotationen, die sich wiederholenden und fehleranfälligen Boilerplate-Code minimieren
- Optimierte Datenbankmigrationspfade
Wir empfehlen, Room anstelle der direkten Verwendung der SQLite-APIs zu verwenden.
Einrichtung
Wenn Sie Room in Ihrer App verwenden möchten, fügen Sie der Datei build.gradle.kts Ihres Moduls die folgenden Abhängigkeiten hinzu: Für Room 3.0 ist KSP für die Annotationenverarbeitung erforderlich.
Kotlin
dependencies { val room_version = "3.0.0" implementation("androidx.room3:room3-runtime:$room_version") ksp("androidx.room3:room3-compiler:$room_version") }
Groovy
dependencies { def room_version = "3.0.0" implementation "androidx.room3:room3-runtime:$room_version" ksp "androidx.room3:room3-compiler:$room_version" }
Hauptkomponenten
Room besteht aus drei Hauptkomponenten:
- Die Datenbankklasse, die die Datenbank enthält und als Hauptzugriff spunkt für die zugrunde liegende Verbindung zu den persistenten Daten Ihrer App dient.
- Die Datenentitäten, die Tabellen in der Datenbank Ihrer App darstellen.
- Die Data Access Objects (DAOs), die Funktionen bereitstellen, mit denen Ihre App Daten in der Datenbank abfragen, aktualisieren, einfügen und löschen kann.
Die Datenbankklasse stellt Ihrer App Instanzen der DAOs zur Verfügung, die mit dieser Datenbank verknüpft sind. Die App kann die DAOs wiederum verwenden, um Daten aus der Datenbank als Instanzen der zugehörigen Datenentitätsobjekte abzurufen. Die App kann die definierten Datenentitäten auch verwenden, um Zeilen aus den entsprechenden Tabellen zu aktualisieren oder neue Zeilen zum Einfügen zu erstellen. Abbildung 1 veranschaulicht die Beziehung zwischen den verschiedenen Komponenten von Room.
Implementierungsbeispiel
In diesem Abschnitt wird eine Beispielimplementierung einer Room-Datenbank mit einer einzelnen Datenentität und einem einzelnen DAO vorgestellt.
Datenentität
Der folgende Code definiert eine User-Datenentität. Jede Instanz von User stellt eine Zeile in einer user-Tabelle in der Datenbank der App dar.
@Entity data class User( @PrimaryKey val uid: Int, @ColumnInfo(name = "first_name") val firstName: String, @ColumnInfo(name = "last_name") val lastName: String )
Weitere Informationen zu Datenentitäten in Room finden Sie unter Daten mit Room Entitäten definieren.
Data Access Object (DAO)
Der folgende Code definiert ein DAO namens UserDao. UserDao stellt die Funktionen bereit, mit denen der Rest der App mit Daten in der user-Tabelle interagiert.
@Dao interface UserDao { @Query("SELECT * FROM user") suspend fun getAll(): List<User> @Query("SELECT * FROM user WHERE uid IN (:userIds)") suspend fun loadAllByIds(userIds: IntArray): List<User> @Query( """ SELECT * FROM user WHERE first_name LIKE :first AND last_name LIKE :last LIMIT 1 """ ) suspend fun findByName(first: String, last: String): User @Insert suspend fun insertAll(vararg users: User) @Delete suspend fun delete(user: User) }
Weitere Informationen zu DAOs finden Sie unter Mit Room DAOs auf Daten zugreifen.
Datenbank
Der folgende Code definiert eine AppDatabase-Klasse, die die Datenbank enthält.
AppDatabase definiert die Datenbankkonfiguration und dient als Hauptzugriffspunkt der App für die persistenten Daten. Die Datenbankklasse muss die folgenden Bedingungen erfüllen:
- Die Klasse muss mit einer
@Database-Annotation versehen sein, die einentities-Array enthält, in dem alle mit der Datenbank verknüpften Datenentitäten aufgeführt sind. - Die Klasse muss eine abstrakte Klasse sein, die
RoomDatabaseerweitert. - Für jede DAO-Klasse, die mit der Datenbank verknüpft ist, muss die Datenbankklasse eine abstrakte Funktion definieren, die keine Argumente akzeptiert und eine Instanz der DAO-Klasse zurückgibt.
@Database(entities = [User::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao }
Hinweis: Wenn Ihre App in einem einzelnen Prozess ausgeführt wird, sollten Sie beim Instanziieren eines AppDatabase
-Objekts dem
Singleton-Entwurfsmuster folgen. Jede RoomDatabase Instanz ist relativ teuer und Sie
benötigen selten Zugriff auf mehrere Instanzen innerhalb eines einzelnen Prozesses.
Wenn Ihre App in mehreren Prozessen ausgeführt wird, fügen Sie
enableMultiInstanceInvalidation() in den Aufruf des Datenbank-Builders
ein. Wenn Sie also in jedem Prozess eine Instanz von AppDatabase
haben, können Sie die freigegebene Datenbankdatei in einem Prozess ungültig machen,
und diese Ungültigmachung wird automatisch an die Instanzen von
AppDatabase in anderen Prozessen weitergegeben.
Nutzung
Nachdem Sie die Datenentität, das DAO und das Datenbankobjekt definiert haben, können Sie mit dem folgenden Code eine Instanz der Datenbank erstellen:
val db = Room.databaseBuilder<AppDatabase>(applicationContext, "database-name") .setDriver(AndroidSQLiteDriver()) .build()
Anschließend können Sie die abstrakten Funktionen aus AppDatabase verwenden, um eine Instanz des DAO abzurufen. Sie können die Funktionen aus der DAO-Instanz wiederum verwenden, um mit der Datenbank zu interagieren:
val userDao = db.userDao() val users: List<User> = userDao.getAll()
Zusätzliche Ressourcen
Weitere Informationen zu Room finden Sie in den folgenden zusätzlichen Ressourcen: