Para impedir que as consultas bloqueiem a IU, o Room não permite o acesso ao banco de dados na linha de execução principal. Devido a essa restrição, é necessário fazer com que as consultas DAO sejam assíncronas. A biblioteca do Room inclui integrações com vários frameworks diferentes para oferecer a execução de consulta assíncrona.
As consultas DAO se enquadram em três categorias:
- Consultas de gravação única, que inserem, atualizam ou excluem dados do banco de dados.
- Consultas de leitura única, que leem dados do banco de dados apenas uma vez e retornam um resultado com um snapshot do banco de dados naquele momento.
- Consultas de leitura observável, que leem dados do banco de dados sempre que as tabelas subjacentes mudam e emitem novos valores para refletir essas mudanças.
Opções de linguagem e framework
O Room oferece suporte de integração para interoperabilidade com bibliotecas e recursos de linguagem específicos. A tabela abaixo mostra os tipos de retorno aplicáveis de acordo com o tipo de consulta e framework:
Tipo de consulta | Recursos da linguagem Kotlin | RxJava | Guava | Ciclo de vida do Jetpack |
---|---|---|---|---|
Gravação única | Corrotinas (suspend ) |
Single<T> , Maybe<T> ,
Completable |
ListenableFuture<T> |
N/A |
Leitura única | Corrotinas (suspend ) |
Single<T> , Maybe<T> |
ListenableFuture<T> |
N/A |
Leitura observável | Flow<T> |
Flowable<T> , Publisher<T> ,
Observable<T> |
N/A | LiveData<T> |
Este guia demonstra três maneiras possíveis de usar essas integrações para implementar consultas assíncronas nos DAOs.
Kotlin com fluxo e corrotinas
O Kotlin oferece recursos de linguagem que permitem criar consultas assíncronas sem frameworks de terceiros:
- No Room 2.2 e versões mais recentes, é possível usar a funcionalidade Flow do Kotlin para criar consultas observáveis.
- No Room 2.1 e versões mais recentes, é possível usar a palavra-chave
suspend
para tornar as consultas do DAO assíncronas, usando corrotinas do Kotlin.
Java com RxJava
Se o app usa a linguagem de programação Java, é possível usar tipos de retorno especializados do framework RxJava para programar métodos DAO assíncronos. O Room oferece suporte a estes tipos de retorno RxJava 2:
- Para consultas únicas, o Room 2.1 e versões mais recentes oferecem suporte aos
tipos de retorno
Completable
,Single<T>
eMaybe<T>
. - Para consultas observáveis, o Room oferece suporte aos
tipos de retorno
Publisher<T>
,Flowable<T>
eObservable<T>
.
Além disso, o Room 2.3 e versões mais recentes oferecem suporte ao RxJava 3.
Java com LiveData e Guava
Se o app usa a linguagem de programação Java e você não quer usar o framework RxJava, é possível usar estas alternativas para programar consultas assíncronas:
- Você pode usar a classe de wrapper
LiveData
do Jetpack para programar consultas observáveis assíncronas. - É possível usar o wrapper
ListenableFuture<T>
do Guava para programar consultas assíncronas únicas.
Criar consultas assíncronas únicas
Consultas únicas são operações de banco de dados que são executadas apenas uma vez e capturam um snapshot dos dados durante a execução. Veja abaixo alguns exemplos de consultas assíncronas únicas:
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); }
Criar consultas observáveis
Consultas observáveis são operações de leitura que emitem novos valores sempre que há mudanças em qualquer uma das tabelas referenciadas pela consulta. Essa função pode ser usada para ajudar a manter uma lista de itens exibida atualizada à medida que os itens no banco de dados são inseridos, atualizados ou removidos. Veja abaixo alguns exemplos de consultas observáveis:
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); }
Outros recursos
Para saber mais sobre consultas DAO assíncronas, consulte os recursos abaixo recursos:
Blogs
- Room e Flow (link em inglês)