Написание асинхронных запросов DAO

Чтобы запросы не блокировали пользовательский интерфейс, 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 см. в следующих дополнительных ресурсах:

Блоги