Para evitar que las consultas bloqueen la IU, Room no permite el acceso a la base de datos en el subproceso principal. Esta restricción implica que tus búsquedas DAO deben ser asíncronas. La biblioteca de Room incluye integraciones con varios frameworks diferentes a fin de permitir la ejecución de búsquedas asíncronas.
Las búsquedas DAO se dividen en tres categorías:
- Búsquedas de escritura única que insertan, actualizan o borran datos en la base de datos.
- Búsquedas de lectura única que leen datos de tu base de datos solo una vez y muestran un resultado con la instantánea de la base de datos en ese momento.
- Búsquedas de lectura observable que leen datos de tu base de datos cada vez que cambian las tablas de la base de datos subyacentes y emiten valores nuevos para reflejar esos cambios.
Opciones de framework y lenguaje
Room admite la interoperabilidad con funciones de lenguaje y bibliotecas específicas. En la siguiente tabla, se muestran los tipos de devolución aplicables según el tipo de búsqueda y el framework:
Tipo de búsqueda | Funciones del lenguaje Kotlin | RxJava | Guava | Ciclo de vida de Jetpack |
---|---|---|---|---|
Escritura por única vez | Corrutinas (suspend ) |
Single<T> , Maybe<T> ,
Completable |
ListenableFuture<T> |
N/A |
Lectura de una toma | Corrutinas (suspend ) |
Single<T> , Maybe<T> |
ListenableFuture<T> |
N/A |
Lectura observable | Flow<T> |
Flowable<T> , Publisher<T> ,
Observable<T> |
N/A | LiveData<T> |
En esta guía, se muestran tres formas posibles de usar estas integraciones para implementar búsquedas asíncronas en tus DAO.
Kotlin con flujo y corrutinas
Kotlin ofrece las siguientes funciones de lenguaje que te permiten escribir consultas asíncronas sin frameworks de terceros:
- En Room 2.2 y versiones posteriores, puedes usar la funcionalidad Flow de Kotlin para escribir consultas observables.
- En Room 2.1 y versiones posteriores, puedes usar la palabra clave
suspend
para que tus consultas DAO sean asíncronas mediante corrutinas de Kotlin.
Java con RxJava
Si tu app usa el lenguaje de programación Java, puedes usar tipos de datos que se muestran especializados desde el framework de RxJava para escribir métodos DAO asíncronos. Room proporciona compatibilidad con los siguientes tipos de datos que se muestran de RxJava 2:
- Para consultas únicas, Room 2.1 y versiones posteriores admiten los tipos de datos que se muestran
Completable
,Single<T>
yMaybe<T>
. - Para las consultas observables, Room admite los tipos de datos que se muestran
Publisher<T>
,Flowable<T>
yObservable<T>
.
Además, Room 2.3 y versiones posteriores son compatibles con RxJava 3.
Java con LiveData y Guava
Si tu app usa el lenguaje de programación Java y no deseas utilizar el marco de trabajo de RxJava, puedes usar las siguientes alternativas para escribir búsquedas asíncronas:
- Puedes usar la clase de wrapper
LiveData
de Jetpack para escribir consultas observables asíncronas. - Puedes usar el wrapper
ListenableFuture<T>
de Guava para escribir consultas asíncronas únicas.
Escritura de búsquedas asíncronas únicas
Las búsquedas únicas son operaciones de base de datos que solo se ejecutan una vez y toman una instantánea de los datos en el momento de la ejecución. Estos son algunos ejemplos de búsquedas así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); }
Escritura de búsquedas observables
Las búsquedas observables son operaciones de lectura que emiten valores nuevos cada vez que hay cambios en cualquiera de las tablas a las que hace referencia la búsqueda. Una forma de usarlas es para ayudarte a mantener actualizada una lista de elementos a medida que se insertan, actualizan o quitan los elementos de la base de datos subyacente. Los siguientes son ejemplos comunes de búsquedas observables:
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); }
Recursos adicionales
Si deseas obtener más información sobre las búsquedas DAO asíncronas, consulta los siguientes recursos adicionales: