Asynchrone DAO-Abfragen schreiben

Damit Abfragen die UI nicht blockieren, lässt Room keinen Datenbankzugriff auf den Hauptthread zu. Diese Einschränkung bedeutet, dass Sie Ihre DAO-Abfragen asynchron machen müssen. Die Room-Bibliothek enthält Integrationen mit mehreren verschiedenen Frameworks, um eine asynchrone Abfrageausführung zu ermöglichen.

DAO-Abfragen lassen sich in drei Kategorien unterteilen:

  • One-Shot-Write-Abfragen, mit denen Daten in die Datenbank eingefügt, aktualisiert oder gelöscht werden.
  • One-Shot-Leseabfragen, die Daten nur einmal aus der Datenbank lesen und zu diesem Zeitpunkt ein Ergebnis mit dem Snapshot der Datenbank zurückgeben.
  • Beobachtbare Leseabfragen, die jedes Mal Daten aus der Datenbank lesen, wenn sich die zugrunde liegenden Datenbanktabellen ändern, und neue Werte ausgeben, um diese Änderungen widerzuspiegeln.

Sprach- und Framework-Optionen

Room bietet Integrationsunterstützung für die Interoperabilität mit bestimmten Sprachfunktionen und Bibliotheken. Die folgende Tabelle zeigt die anwendbaren Rückgabetypen basierend auf dem Abfragetyp und dem Framework:

Abfragetyp Kotlin-Sprachfunktionen RxJava Guava Jetpack-Lebenszyklus
One-Shot-Write Koroutinen (suspend) Single<T>, Maybe<T>, Completable ListenableFuture<T>
One-Shot-Artikel Koroutinen (suspend) Single<T>, Maybe<T> ListenableFuture<T>
Beobachtbarer Lesevorgang Flow<T> Flowable<T>, Publisher<T>, Observable<T> LiveData<T>

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

Kotlin mit Flow und Couroutinen

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 Schlüsselwort suspend verwenden, um Ihre DAO-Abfragen mithilfe von Kotlin-Koroutinen asynchron zu machen.

Java mit RxJava

Wenn Ihre Anwendung die Programmiersprache Java verwendet, 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 Raum 2.3 und höher RxJava 3.

Java mit LiveData und Guava

Wenn Ihre Anwendung die Programmiersprache Java verwendet und Sie das RxJava-Framework nicht verwenden möchten, können Sie die folgenden Alternativen verwenden, um asynchrone Abfragen zu schreiben:

  • Mit der Wrapper-Klasse LiveData von Jetpack können Sie asynchrone, beobachtbare Abfragen schreiben.
  • Mit dem ListenableFuture<T>-Wrapper von Guava können Sie asynchrone Abfragen mit nur einer Aufnahme schreiben.

Asynchrone Abfragen mit einer einzigen Aufnahme schreiben

One-Shot-Abfragen sind Datenbankvorgänge, die nur einmal ausgeführt werden und bei der Ausführung einen Snapshot der Daten erfassen. Hier sind einige Beispiele für asynchrone Einzelabfragen:

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 es Änderungen an einer der Tabellen gibt, auf die die Abfrage verweist. Eine Möglichkeit, die Sie so verwenden können, besteht darin, die angezeigte Liste von Elementen beim Einfügen, Aktualisieren oder Entfernen der Elemente in der zugrunde liegenden Datenbank auf dem neuesten Stand zu halten. Hier sind 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 Ressourcen:

Produktproben

Blogs