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:
- W przypadku zapytań jednorazowych Room 2.1 i nowsze obsługują typy zwracania
Completable
,Single<T>
iMaybe<T>
. - W przypadku zapytań obserwowalnych Room obsługuje typy zwracania
Publisher<T>
,Flowable<T>
iObservable<T>
.
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: