Чтобы запросы не блокировали пользовательский интерфейс, Room не разрешает доступ к базе данных в основном потоке. Это ограничение означает, что вы должны сделать запросы DAO асинхронными. Библиотека Room включает интеграцию с несколькими различными платформами для обеспечения асинхронного выполнения запросов.
Запросы DAO делятся на три категории:
- Одноразовые запросы на запись , которые вставляют, обновляют или удаляют данные в базе данных.
- Запросы на однократное чтение , которые считывают данные из вашей базы данных только один раз и возвращают результат со снимком базы данных в этот момент.
- Наблюдаемые запросы чтения , которые считывают данные из вашей базы данных каждый раз, когда изменяются базовые таблицы базы данных, и выдают новые значения, отражающие эти изменения.
Параметры языка и платформы
Room обеспечивает поддержку интеграции для взаимодействия с конкретными языковыми функциями и библиотеками. В следующей таблице показаны применимые типы возвращаемых данных в зависимости от типа запроса и платформы:
Тип запроса | Особенности языка Котлин | RxJava | Гуава | Жизненный цикл реактивного ранца |
---|---|---|---|---|
Однократная запись | Сопрограммы ( suspend ) | Single<T> , Maybe<T> , Completable | ListenableFuture<T> | Н/Д |
Одноразовое чтение | Сопрограммы ( suspend ) | Single<T> , Maybe<T> | ListenableFuture<T> | Н/Д |
Наблюдаемое чтение | Flow<T> | Flowable<T> , Publisher<T> , Observable<T> | Н/Д | LiveData<T> |
В этом руководстве демонстрируются три возможных способа использования этих интеграций для реализации асинхронных запросов в ваших DAO.
Котлин с Flow и курутинами
Kotlin предоставляет возможности языка, которые позволяют писать асинхронные запросы без сторонних фреймворков:
- В комнате 2.2 и выше вы можете использовать функциональность Kotlin Flow для написания наблюдаемых запросов.
- В версии 2.1 и выше вы можете использовать ключевое слово
suspend
, чтобы сделать запросы DAO асинхронными с использованием сопрограмм Kotlin .
Java с RxJava
Если ваше приложение использует язык программирования Java, вы можете использовать специализированные типы возвращаемых данных из платформы RxJava для написания асинхронных методов DAO. Room обеспечивает поддержку следующих типов возврата RxJava 2:
- Для однократных запросов Room 2.1 и выше поддерживают типы возвращаемых данных
Completable
,Single<T>
иMaybe<T>
. - Для наблюдаемых запросов Room поддерживает типы возвращаемых значений
Publisher<T>
,Flowable<T>
иObservable<T>
.
Кроме того, Room 2.3 и выше поддерживают RxJava 3.
Java с LiveData и Guava
Если ваше приложение использует язык программирования Java и вы не хотите использовать платформу RxJava, вы можете использовать следующие альтернативы для написания асинхронных запросов:
- Вы можете использовать класс-оболочку
LiveData
из Jetpack для написания асинхронных наблюдаемых запросов. - Вы можете использовать оболочку
ListenableFuture<T>
из Guava для написания асинхронных одноразовых запросов.
Написание асинхронных одноразовых запросов
Одноразовые запросы — это операции с базой данных, которые выполняются только один раз и во время выполнения получают снимок данных. Вот несколько примеров асинхронных одноразовых запросов:
Котлин
@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> }
Ява
@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); }
Ява
@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); }
Пишите наблюдаемые запросы
Наблюдаемые запросы — это операции чтения, которые выдают новые значения всякий раз, когда происходят изменения в любой из таблиц, на которые ссылается запрос. Один из способов использования этого — поддерживать актуальность отображаемого списка элементов по мере того, как элементы в базовой базе данных вставляются, обновляются или удаляются. Вот несколько примеров наблюдаемых запросов:
Котлин
@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>> }
Ява
@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); }
Ява
@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); }
Дополнительные ресурсы
Дополнительные сведения об асинхронных запросах DAO см. в следующих дополнительных ресурсах: