Asynchrone DAO-Abfragen schreiben

Damit Abfragen die Benutzeroberfläche nicht blockieren, erlaubt Room keinen Datenbankzugriff auf den Hauptthread. Diese Einschränkung bedeutet, dass Sie Ihre DAO-Abfragen asynchron ausführen müssen. Die Room-Bibliothek bietet Integrationen mit mehreren verschiedenen Frameworks für die asynchrone Abfrageausführung.

DAO-Abfragen lassen sich in drei Kategorien unterteilen:

  • Einmal schreiben-Abfragen, die Daten in die Datenbank einfügen, aktualisieren oder löschen.
  • Einmalleseabfragen, bei denen Daten nur einmal aus der Datenbank gelesen und ein Ergebnis mit dem Snapshot der Datenbank zu diesem Zeitpunkt zurückgegeben werden.
  • Beobachtbare Leseabfragen, bei denen jedes Mal, wenn sich die zugrunde liegenden Datenbanktabellen ändern, Daten aus Ihrer Datenbank gelesen und neue Werte ausgegeben werden, um diese Änderungen widerzuspiegeln.

Sprach- und Frameworkoptionen

Room bietet Integrationsunterstützung für die Interoperabilität mit bestimmten Sprachfunktionen und ‑bibliotheken. In der folgenden Tabelle sind die zulässigen Rückgabetypen nach Abfragetyp und Framework aufgeführt:

Abfragetyp Kotlin-Sprachfunktionen RxJava Guava Jetpack Lifecycle
Einmaliger Schreibvorgang Coroutinen (suspend) Single<T>, Maybe<T>, Completable ListenableFuture<T>
Einmaliges Lesen Coroutinen (suspend) Single<T>, Maybe<T> ListenableFuture<T>
Observable read Flow<T> Flowable<T>, Publisher<T>, Observable<T> LiveData<T>

In diesem Leitfaden werden drei Möglichkeiten beschrieben, wie Sie diese Integrationen verwenden können, um asynchrone Abfragen in Ihren DAOs zu implementieren.

Kotlin mit Flow und Coroutines

Kotlin bietet Sprachfunktionen, mit denen Sie asynchrone Abfragen ohne Frameworks von Drittanbietern schreiben können:

  • In Room 2.2 und höher können Sie die Flow-Funktion von Kotlin verwenden, um beobachtbare Abfragen zu schreiben.
  • In Room 2.1 und höher können Sie das Keyword suspend verwenden, um Ihre DAO-Abfragen mithilfe von Kotlin-Coroutines asynchron auszuführen.

Java mit RxJava

Wenn Sie in Ihrer App die Programmiersprache Java verwenden, können Sie spezielle Rückgabetypen aus dem RxJava-Framework verwenden, um asynchrone DAO-Methoden zu schreiben. Room unterstützt die folgenden RxJava 2-Rückgabetypen:

Außerdem unterstützt Room 2.3 und höher RxJava 3.

Java mit LiveData und Guava

Wenn Sie in Ihrer App die Programmiersprache Java verwenden und das RxJava-Framework nicht verwenden möchten, können Sie asynchrone Abfragen mit den folgenden Alternativen schreiben:

  • Sie können die Wrapper-Klasse LiveData von Jetpack verwenden, um asynchrone observable Abfragen zu schreiben.
  • Sie können den ListenableFuture<T>-Wrapper von Guava verwenden, um asynchrone Einmalabfragen zu schreiben.

Asynchrone Einmalabfragen schreiben

Einmalige Abfragen sind Datenbankvorgänge, die nur einmal ausgeführt werden und zum Zeitpunkt der Ausführung einen Snapshot der Daten erfassen. Hier einige Beispiele für asynchrone Einmalabfragen:

Kotlin

@Dao
interface UserDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertUsers(vararg users: User)

    @Update
    suspend fun updateUsers(vararg users: User)

    @Delete
    suspend fun deleteUsers(vararg users: User)

    @Query("SELECT * FROM user WHERE id = :id")
    suspend fun loadUserById(id: Int): User

    @Query("SELECT * from user WHERE region IN (:regions)")
    suspend fun loadUsersByRegion(regions: List<String>): List<User>
}

Java

@Dao
public interface UserDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    public Completable insertUsers(List<User> users);

    @Update
    public Completable updateUsers(List<User> users);

    @Delete
    public Completable deleteUsers(List<User> users);

    @Query("SELECT * FROM user WHERE id = :id")
    public Single<User> loadUserById(int id);

    @Query("SELECT * from user WHERE region IN (:regions)")
    public Single<List<User>> loadUsersByRegion(List<String> regions);
}

Java

@Dao
public interface UserDao {
    // Returns the number of users inserted.
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    public ListenableFuture<Integer> insertUsers(List<User> users);

    // Returns the number of users updated.
    @Update
    public ListenableFuture<Integer> updateUsers(List<User> users);

    // Returns the number of users deleted.
    @Delete
    public ListenableFuture<Integer> deleteUsers(List<User> users);

    @Query("SELECT * FROM user WHERE id = :id")
    public ListenableFuture<User> loadUserById(int id);

    @Query("SELECT * from user WHERE region IN (:regions)")
    public ListenableFuture<List<User>> loadUsersByRegion(List<String> regions);
}

Beobachtbare Abfragen schreiben

Beobachtbare Abfragen sind Lesevorgänge, die neue Werte ausgeben, wenn sich eine der Tabellen ändert, auf die in der Abfrage verwiesen wird. So können Sie beispielsweise eine angezeigte Artikelliste auf dem neuesten Stand halten, wenn Artikel in der zugrunde liegenden Datenbank eingefügt, aktualisiert oder entfernt werden. Hier einige Beispiele für beobachtbare Abfragen:

Kotlin

@Dao
interface UserDao {
    @Query("SELECT * FROM user WHERE id = :id")
    fun loadUserById(id: Int): Flow<User>

    @Query("SELECT * from user WHERE region IN (:regions)")
    fun loadUsersByRegion(regions: List<String>): Flow<List<User>>
}

Java

@Dao
public interface UserDao {
    @Query("SELECT * FROM user WHERE id = :id")
    public Flowable<User> loadUserById(int id);

    @Query("SELECT * from user WHERE region IN (:regions)")
    public Flowable<List<User>> loadUsersByRegion(List<String> regions);
}

Java

@Dao
public interface UserDao {
    @Query("SELECT * FROM user WHERE id = :id")
    public LiveData<User> loadUserById(int id);

    @Query("SELECT * from user WHERE region IN (:regions)")
    public LiveData<List<User>> loadUsersByRegion(List<String> regions);
}

Weitere Informationen

Weitere Informationen zu asynchronen DAO-Abfragen finden Sie in den folgenden zusätzlichen Ressourcen:

Blogs