Speichern Sie Daten in einer lokalen Datenbank mit Room Teil von Android Jetpack.

Anwendungen, die komplexe Mengen strukturierter Daten verarbeiten, können enorm davon profitieren, diese Daten lokal zu speichern. Am häufigsten werden relevante Daten im Cache gespeichert. Wenn das Gerät nicht auf das Netzwerk zugreifen kann, kann der Nutzer diese Inhalte auch dann durchsuchen, wenn er offline ist.

Die Room-Persistence-Bibliothek bietet eine Abstraktionsebene über SQLite, um einen fließenden Zugriff auf die Datenbank zu ermöglichen und gleichzeitig die volle Leistung von SQLite zu nutzen. Room bietet insbesondere folgende Vorteile:

  • Verifizierung während der Kompilierung von SQL-Abfragen.
  • Praktische Anmerkungen, die sich wiederholenden und fehleranfälligen Boilerplate-Code minimieren.
  • Optimierte Datenbankmigrationspfade.

Aufgrund dieser Überlegungen empfehlen wir dringend, den Raum zu verwenden, anstatt die SQLite APIs direkt zu nutzen.

Einrichten

Wenn Sie Room in Ihrer Anwendung verwenden möchten, fügen Sie der Datei build.gradle der Anwendung die folgenden Abhängigkeiten hinzu:

Groovig

dependencies {
    def room_version = "2.6.1"

    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version"

    // To use Kotlin annotation processing tool (kapt)
    kapt "androidx.room:room-compiler:$room_version"
    // To use Kotlin Symbol Processing (KSP)
    ksp "androidx.room:room-compiler:$room_version"

    // optional - RxJava2 support for Room
    implementation "androidx.room:room-rxjava2:$room_version"

    // optional - RxJava3 support for Room
    implementation "androidx.room:room-rxjava3:$room_version"

    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation "androidx.room:room-guava:$room_version"

    // optional - Test helpers
    testImplementation "androidx.room:room-testing:$room_version"

    // optional - Paging 3 Integration
    implementation "androidx.room:room-paging:$room_version"
}

Kotlin

dependencies {
    val room_version = "2.6.1"

    implementation("androidx.room:room-runtime:$room_version")
    annotationProcessor("androidx.room:room-compiler:$room_version")

    // To use Kotlin annotation processing tool (kapt)
    kapt("androidx.room:room-compiler:$room_version")
    // To use Kotlin Symbol Processing (KSP)
    ksp("androidx.room:room-compiler:$room_version")

    // optional - Kotlin Extensions and Coroutines support for Room
    implementation("androidx.room:room-ktx:$room_version")

    // optional - RxJava2 support for Room
    implementation("androidx.room:room-rxjava2:$room_version")

    // optional - RxJava3 support for Room
    implementation("androidx.room:room-rxjava3:$room_version")

    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation("androidx.room:room-guava:$room_version")

    // optional - Test helpers
    testImplementation("androidx.room:room-testing:$room_version")

    // optional - Paging 3 Integration
    implementation("androidx.room:room-paging:$room_version")
}

Hauptkomponenten

In Room gibt es drei Hauptkomponenten:

  • Die Datenbankklasse mit der Datenbank und Hauptzugriffspunkt für die zugrunde liegende Verbindung zu den persistenten Daten Ihrer Anwendung.
  • Datenentitäten, die Tabellen in der Datenbank Ihrer Anwendung darstellen
  • Datenzugriffsobjekte (Data Access Objects, DAOs), die Methoden bereitstellen, mit denen Ihre Anwendung Daten in der Datenbank abfragen, aktualisieren, einfügen und löschen kann.

Die Datenbankklasse stellt Ihrer Anwendung Instanzen der DAOs bereit, die mit dieser Datenbank verknüpft sind. Die Anwendung kann wiederum die DAOs verwenden, um Daten aus der Datenbank als Instanzen der verknüpften Datenentitätsobjekte abzurufen. Die Anwendung kann die definierten Datenentitäten auch verwenden, um Zeilen aus den entsprechenden Tabellen zu aktualisieren oder neue Zeilen für das Einfügen zu erstellen. In Abbildung 1 sehen Sie die Beziehung zwischen den verschiedenen Raumkomponenten.

Abbildung 1: Diagramm der Architektur der Raumbibliothek

Implementierungsbeispiel

In diesem Abschnitt wird eine Beispielimplementierung einer Raumdatenbank mit einer einzelnen Datenentität und einem einzelnen DAO vorgestellt.

Datenentität

Mit dem folgenden Code wird eine User-Datenentität definiert. Jede Instanz von User stellt eine Zeile in einer user-Tabelle in der Datenbank der Anwendung dar.

Kotlin

@Entity
data class User(
    @PrimaryKey val uid: Int,
    @ColumnInfo(name = "first_name") val firstName: String?,
    @ColumnInfo(name = "last_name") val lastName: String?
)

Java

@Entity
public class User {
    @PrimaryKey
    public int uid;

    @ColumnInfo(name = "first_name")
    public String firstName;

    @ColumnInfo(name = "last_name")
    public String lastName;
}

Weitere Informationen zu Datenentitäten in Room finden Sie unter Daten mithilfe von Room-Entitäten definieren.

Datenzugriffsobjekt (DAO)

Mit dem folgenden Code wird ein DAO mit dem Namen UserDao definiert. UserDao stellt die Methoden bereit, die der Rest der Anwendung für die Interaktion mit Daten in der Tabelle user verwendet.

Kotlin

@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    fun getAll(): List<User>

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    fun loadAllByIds(userIds: IntArray): List<User>

    @Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
           "last_name LIKE :last LIMIT 1")
    fun findByName(first: String, last: String): User

    @Insert
    fun insertAll(vararg users: User)

    @Delete
    fun delete(user: User)
}

Java

@Dao
public interface UserDao {
    @Query("SELECT * FROM user")
    List<User> getAll();

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    List<User> loadAllByIds(int[] userIds);

    @Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
           "last_name LIKE :last LIMIT 1")
    User findByName(String first, String last);

    @Insert
    void insertAll(User... users);

    @Delete
    void delete(User user);
}

Weitere Informationen zu DAOs finden Sie unter Mit Raum-DAOs auf Daten zugreifen.

Datenbank

Mit dem folgenden Code wird eine AppDatabase-Klasse für die Datenbank definiert. AppDatabase definiert die Datenbankkonfiguration und dient als Hauptzugriffspunkt der Anwendung auf die gespeicherten Daten. Die Datenbankklasse muss die folgenden Bedingungen erfüllen:

  • Die Klasse muss mit einer @Database-Annotation annotiert werden, die ein entities-Array enthält, in dem alle mit der Datenbank verknüpften Datenentitäten aufgelistet sind.
  • Die Klasse muss eine abstrakte Klasse sein, die RoomDatabase erweitert.
  • Für jede mit der Datenbank verknüpfte DAO-Klasse muss die Datenbankklasse eine abstrakte Methode definieren, die keine Argumente hat und eine Instanz der DAO-Klasse zurückgibt.

Kotlin

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

Java

@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
}

Hinweis : Wenn Ihre Anwendung in einem einzigen Prozess ausgeführt wird, sollten Sie beim Instanziieren eines AppDatabase-Objekts dem Singleton-Designmuster folgen. Jede RoomDatabase-Instanz ist relativ teuer und Sie benötigen selten Zugriff auf mehrere Instanzen innerhalb eines einzelnen Prozesses.

Wenn Ihre Anwendung in mehreren Prozessen ausgeführt wird, fügen Sie enableMultiInstanceInvalidation() in den Aufruf des Database Builder ein. Wenn also in jedem Prozess eine Instanz von AppDatabase vorhanden ist, können Sie die freigegebene Datenbankdatei in einem Prozess entwerten. Diese Entwertung wird dann automatisch an die Instanzen von AppDatabase in anderen Prozessen weitergegeben.

Nutzung

Nachdem Sie die Datenentität, die DAO und das Datenbankobjekt definiert haben, können Sie mit dem folgenden Code eine Instanz der Datenbank erstellen:

Kotlin

val db = Room.databaseBuilder(
            applicationContext,
            AppDatabase::class.java, "database-name"
        ).build()

Java

AppDatabase db = Room.databaseBuilder(getApplicationContext(),
        AppDatabase.class, "database-name").build();

Sie können dann die abstrakten Methoden aus dem AppDatabase verwenden, um eine Instanz der DAO abzurufen. Sie können wiederum die Methoden der DAO-Instanz verwenden, um mit der Datenbank zu interagieren:

Kotlin

val userDao = db.userDao()
val users: List<User> = userDao.getAll()

Java

UserDao userDao = db.userDao();
List<User> users = userDao.getAll();

Weitere Informationen

Weitere Informationen zu Room finden Sie in den folgenden Ressourcen:

Produktproben

Codelabs

Blogs