Zapisz asynchroniczne zapytania DAO

Aby zapytania nie blokowały interfejsu użytkownika, Room nie zezwala na dostęp do bazy danych na głównym wątku. To ograniczenie oznacza, że musisz zadbać o asychronowość zapytań DAO. Biblioteka Room zawiera integracje z kilkoma różnymi platformami, aby zapewnić asynchroniczne wykonywanie zapytań.

Zapytania DAO dzielą się na 3 kategorie:

  • Jednorazowe operacje zapisu, które wstawiają, aktualizują lub usuwają dane w bazie danych.
  • Zapytania jednorazowe, które odczytują dane z bazy danych tylko raz i zwracają wynik z jej bieżącego stanu.
  • Obserwowane zapytania odczytu, które odczytują dane z Twojej bazy danych za każdym razem, gdy zmieniają się jej tabele źródłowe, i wydają nowe wartości, aby odzwierciedlić te zmiany.

Opcje języka i ramy

Room zapewnia obsługę integracji w celu zapewnienia interoperacyjności z określonymi funkcjami językowymi i bibliotekami. Tabela poniżej przedstawia odpowiednie typy danych wyjściowych na podstawie typu zapytania i ramy:

Typ zapytania Funkcje języka Kotlin RxJava Gujawa Jetpack Lifecycle
Prompt „one-shot” Coroutines (suspend) Single<T>, Maybe<T>, Completable ListenableFuture<T> Nie dotyczy
Jednorazowe odczytanie Coroutines (suspend) Single<T>, Maybe<T> ListenableFuture<T> Nie dotyczy
Observable read Flow<T> Flowable<T>, Publisher<T>, Observable<T> Nie dotyczy LiveData<T>

W tym przewodniku przedstawiamy 3 możliwe sposoby korzystania z tych integracji do implementowania zapytań asynchronicznych w DAO.

Kotlin z Flow i kooroutines

Kotlin udostępnia funkcje języka, które umożliwiają tworzenie zapytań asynchronicznych bez ramek innych firm:

  • W wersji Room 2.2 i wyższych możesz używać funkcji Flow w Kotlinie do pisania zapytań z obserwowalnymi wynikami.
  • W Room 2.1 i nowszych wersjach możesz użyć słowa kluczowego suspend, aby zapytania DAO były asynchroniczne, korzystając z korektu Kotlina.

Java z RxJava

Jeśli Twoja aplikacja korzysta z języka programowania Java, możesz użyć wyspecjalizowanych typów zwracanych z platformy RxJava, aby pisać asynchroniczne metody DAO. Room obsługuje te typy zwracane przez RxJava 2:

Dodatkowo Room w wersji 2.3 i nowszej obsługuje RxJava 3.

Java z LiveData i Guava

Jeśli Twoja aplikacja korzysta z języka programowania Java i nie chcesz używać platformy RxJava, możesz użyć tych alternatyw do pisania zapytań asynchronicznych:

  • Aby pisać asynchroniczne zapytania observable, możesz użyć klasy opakowującej LiveData z Jetpacka.
  • Aby pisać asynchroniczne zapytania jednorazowe, możesz użyć opakowania ListenableFuture<T> z Guavy.

Pisanie asynchronicznych zapytań jednorazowych

Zapytania jednorazowe to operacje bazy danych, które są wykonywane tylko raz i w momencie wykonania pobierają migawkę danych. Oto kilka przykładów asynchronicznych zapytań jednorazowych:

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);
}

Tworzenie zapytań do usługi Observeable

Obserwowalne zapytania to operacje odczytu, które emitują nowe wartości, gdy nastąpią zmiany w jakiejkolwiek tabeli, do której odwołuje się zapytanie. Możesz na przykład użyć tego, aby wyświetlana lista elementów była zawsze aktualna, gdy elementy w bazie danych są wstawiane, aktualizowane lub usuwane. Oto kilka przykładów zapytań, które można obserwować:

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);
}

Dodatkowe materiały

Więcej informacji o asynchronicznych zapytaniach DAO znajdziesz w tych dodatkowych materiałach:

Blogi