Organiza tus páginas con colecciones
Guarda y categoriza el contenido según tus preferencias.
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> y Maybe<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
@DaointerfaceUserDao{@Insert(onConflict=OnConflictStrategy.REPLACE)suspendfuninsertUsers(varargusers:User)@UpdatesuspendfunupdateUsers(varargusers:User)@DeletesuspendfundeleteUsers(varargusers:User)@Query("SELECT * FROM user WHERE id = :id")suspendfunloadUserById(id:Int):User@Query("SELECT * from user WHERE region IN (:regions)")suspendfunloadUsersByRegion(regions:List<String>):List<User>}
Java
@DaopublicinterfaceUserDao{@Insert(onConflict=OnConflictStrategy.REPLACE)publicCompletableinsertUsers(List<User>users);@UpdatepublicCompletableupdateUsers(List<User>users);@DeletepublicCompletabledeleteUsers(List<User>users);@Query("SELECT * FROM user WHERE id = :id")publicSingle<User>loadUserById(intid);@Query("SELECT * from user WHERE region IN (:regions)")publicSingle<List<User>>loadUsersByRegion(List<String>regions);}
Java
@DaopublicinterfaceUserDao{// Returns the number of users inserted.@Insert(onConflict=OnConflictStrategy.REPLACE)publicListenableFuture<Integer>insertUsers(List<User>users);// Returns the number of users updated.@UpdatepublicListenableFuture<Integer>updateUsers(List<User>users);// Returns the number of users deleted.@DeletepublicListenableFuture<Integer>deleteUsers(List<User>users);@Query("SELECT * FROM user WHERE id = :id")publicListenableFuture<User>loadUserById(intid);@Query("SELECT * from user WHERE region IN (:regions)")publicListenableFuture<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
@DaointerfaceUserDao{@Query("SELECT * FROM user WHERE id = :id")funloadUserById(id:Int):Flow<User>@Query("SELECT * from user WHERE region IN (:regions)")funloadUsersByRegion(regions:List<String>):Flow<List<User>>
}
Java
@DaopublicinterfaceUserDao{@Query("SELECT * FROM user WHERE id = :id")publicFlowable<User>loadUserById(intid);@Query("SELECT * from user WHERE region IN (:regions)")publicFlowable<List<User>>loadUsersByRegion(List<String>regions);}
Java
@DaopublicinterfaceUserDao{@Query("SELECT * FROM user WHERE id = :id")publicLiveData<User>loadUserById(intid);@Query("SELECT * from user WHERE region IN (:regions)")publicLiveData<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:
El contenido y las muestras de código que aparecen en esta página están sujetas a las licencias que se describen en la Licencia de Contenido. Java y OpenJDK son marcas registradas de Oracle o sus afiliados.
Última actualización: 2025-07-27 (UTC)
[[["Fácil de comprender","easyToUnderstand","thumb-up"],["Resolvió mi problema","solvedMyProblem","thumb-up"],["Otro","otherUp","thumb-up"]],[["Falta la información que necesito","missingTheInformationINeed","thumb-down"],["Muy complicado o demasiados pasos","tooComplicatedTooManySteps","thumb-down"],["Desactualizado","outOfDate","thumb-down"],["Problema de traducción","translationIssue","thumb-down"],["Problema con las muestras o los códigos","samplesCodeIssue","thumb-down"],["Otro","otherDown","thumb-down"]],["Última actualización: 2025-07-27 (UTC)"],[],[],null,["# Write asynchronous DAO queries\n\nTo prevent queries from blocking the UI, Room does not allow database access on\nthe main thread. This restriction means that you must make your [DAO\nqueries](/training/data-storage/room/accessing-data) asynchronous. The Room\nlibrary includes integrations with several different frameworks to provide\nasynchronous query execution.\n\nDAO queries fall into three categories:\n\n- *One-shot write* queries that insert, update, or delete data in the database.\n- *One-shot read* queries that read data from your database only once and return a result with the snapshot of the database at that time.\n- *Observable read* queries that read data from your database every time the underlying database tables change and emit new values to reflect those changes.\n\nLanguage and framework options\n------------------------------\n\nRoom provides integration support for interoperability with specific language\nfeatures and libraries. The following table shows applicable return types based\non query type and framework:\n\n| Query type | Kotlin language features | RxJava | Guava | Jetpack Lifecycle |\n|-----------------|--------------------------|------------------------------------------------|-----------------------|-------------------|\n| One-shot write | Coroutines (`suspend`) | `Single\u003cT\u003e`, `Maybe\u003cT\u003e`, `Completable` | `ListenableFuture\u003cT\u003e` | N/A |\n| One-shot read | Coroutines (`suspend`) | `Single\u003cT\u003e`, `Maybe\u003cT\u003e` | `ListenableFuture\u003cT\u003e` | N/A |\n| Observable read | `Flow\u003cT\u003e` | `Flowable\u003cT\u003e`, `Publisher\u003cT\u003e`, `Observable\u003cT\u003e` | N/A | `LiveData\u003cT\u003e` |\n\nThis guide demonstrates three possible ways that you can use these integrations\nto implement asynchronous queries in your DAOs.\n\n### Kotlin with Flow and couroutines\n\nKotlin provides language features that allow you to write asynchronous queries\nwithout third-party frameworks:\n\n- In Room 2.2 and higher, you can use Kotlin's [Flow](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/) functionality to write observable queries.\n- In Room 2.1 and higher, you can use the `suspend` keyword to make your DAO queries asynchronous using [Kotlin coroutines](/kotlin/coroutines).\n\n| **Note:** To use Kotlin Flow and coroutines with Room, you must include the `room-ktx` artifact in your `build.gradle` file. For more information, see [Declaring\n| dependencies](/jetpack/androidx/releases/room#declaring_dependencies).\n\n### Java with RxJava\n\nIf your app uses the Java programming language, you can use specialized return\ntypes from the RxJava framework to write asynchronous DAO methods. Room provides\nsupport for the following RxJava 2 return types:\n\n- For one-shot queries, Room 2.1 and higher supports the [`Completable`](http://reactivex.io/RxJava/javadoc/io/reactivex/Completable), [`Single\u003cT\u003e`](http://reactivex.io/RxJava/javadoc/io/reactivex/Single), and [`Maybe\u003cT\u003e`](http://reactivex.io/RxJava/javadoc/io/reactivex/Maybe) return types.\n- For observable queries, Room supports the [`Publisher\u003cT\u003e`](http://www.reactive-streams.org/reactive-streams-1.0.1-javadoc/org/reactivestreams/Publisher), [`Flowable\u003cT\u003e`](http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Flowable), and [`Observable\u003cT\u003e`](http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Observable) return types.\n\nAdditionally, Room 2.3 and higher supports RxJava 3.\n| **Note:** To use RxJava with Room, you must include either the `room-rxjava2` artifact or the `room-rxjava3` artifact in your `build.gradle` file. For more information, see [Declaring\n| dependencies](/jetpack/androidx/releases/room#declaring_dependencies).\n\n### Java with LiveData and Guava\n\nIf your app uses the Java programming language and you do not want to use the\nRxJava framework, you can use the following alternatives to write asynchronous\nqueries:\n\n- You can use the [`LiveData`](/reference/androidx/lifecycle/LiveData) wrapper class from Jetpack to write asynchronous observable queries.\n- You can use the [`ListenableFuture\u003cT\u003e`](https://guava.dev/releases/21.0/api/docs/com/google/common/util/concurrent/ListenableFuture) wrapper from Guava to write asynchronous one-shot queries.\n\n| **Note:** To use Guava with Room, you must include the `room-guava` artifact in your `build.gradle` file. For more information, see [Declaring\n| dependencies](/jetpack/androidx/releases/room#declaring_dependencies).\n\nWrite asynchronous one-shot queries\n-----------------------------------\n\nOne-shot queries are database operations that only run once and grab a snapshot\nof data at the time of execution. Here are some examples of asynchronous\none-shot queries: \n\n### Kotlin\n\n```kotlin\n@Dao\ninterface UserDao {\n @Insert(onConflict = OnConflictStrategy.REPLACE)\n suspend fun insertUsers(vararg users: User)\n\n @Update\n suspend fun updateUsers(vararg users: User)\n\n @Delete\n suspend fun deleteUsers(vararg users: User)\n\n @Query(\"SELECT * FROM user WHERE id = :id\")\n suspend fun loadUserById(id: Int): User\n\n @Query(\"SELECT * from user WHERE region IN (:regions)\")\n suspend fun loadUsersByRegion(regions: List\u003cString\u003e): List\u003cUser\u003e\n}\n```\n\n### Java\n\n```java\n@Dao\npublic interface UserDao {\n @Insert(onConflict = OnConflictStrategy.REPLACE)\n public Completable insertUsers(List\u003cUser\u003e users);\n\n @Update\n public Completable updateUsers(List\u003cUser\u003e users);\n\n @Delete\n public Completable deleteUsers(List\u003cUser\u003e users);\n\n @Query(\"SELECT * FROM user WHERE id = :id\")\n public Single\u003cUser\u003e loadUserById(int id);\n\n @Query(\"SELECT * from user WHERE region IN (:regions)\")\n public Single\u003cList\u003cUser\u003e\u003e loadUsersByRegion(List\u003cString\u003e regions);\n}\n```\n\n### Java\n\n```java\n@Dao\npublic interface UserDao {\n // Returns the number of users inserted.\n @Insert(onConflict = OnConflictStrategy.REPLACE)\n public ListenableFuture\u003cInteger\u003e insertUsers(List\u003cUser\u003e users);\n\n // Returns the number of users updated.\n @Update\n public ListenableFuture\u003cInteger\u003e updateUsers(List\u003cUser\u003e users);\n\n // Returns the number of users deleted.\n @Delete\n public ListenableFuture\u003cInteger\u003e deleteUsers(List\u003cUser\u003e users);\n\n @Query(\"SELECT * FROM user WHERE id = :id\")\n public ListenableFuture\u003cUser\u003e loadUserById(int id);\n\n @Query(\"SELECT * from user WHERE region IN (:regions)\")\n public ListenableFuture\u003cList\u003cUser\u003e\u003e loadUsersByRegion(List\u003cString\u003e regions);\n}\n```\n\nWrite observable queries\n------------------------\n\nObservable queries are read operations that emit new values whenever there are\nchanges to any of the tables that are referenced by the query. One way you might\nuse this is to help you keep a displayed list of items up to date as the items\nin the underlying database are inserted, updated, or removed. Here are some\nexamples of observable queries: \n\n### Kotlin\n\n```kotlin\n@Dao\ninterface UserDao {\n @Query(\"SELECT * FROM user WHERE id = :id\")\n fun loadUserById(id: Int): Flow\u003cUser\u003e\n\n @Query(\"SELECT * from user WHERE region IN (:regions)\")\n fun loadUsersByRegion(regions: List\u003cString\u003e): Flow\u003cList\u003cUser\u003e\u003e\n}\n```\n\n### Java\n\n```java\n@Dao\npublic interface UserDao {\n @Query(\"SELECT * FROM user WHERE id = :id\")\n public Flowable\u003cUser\u003e loadUserById(int id);\n\n @Query(\"SELECT * from user WHERE region IN (:regions)\")\n public Flowable\u003cList\u003cUser\u003e\u003e loadUsersByRegion(List\u003cString\u003e regions);\n}\n```\n\n### Java\n\n```java\n@Dao\npublic interface UserDao {\n @Query(\"SELECT * FROM user WHERE id = :id\")\n public LiveData\u003cUser\u003e loadUserById(int id);\n\n @Query(\"SELECT * from user WHERE region IN (:regions)\")\n public LiveData\u003cList\u003cUser\u003e\u003e loadUsersByRegion(List\u003cString\u003e regions);\n}\n```\n| **Note:** Observable queries in Room have one important limitation: the query reruns whenever any row in the table is updated, whether or not that row is in the result set. You can ensure that the UI is only notified when the actual query results change by applying the `distinctUntilChanged()` operator from the corresponding library: [Flow](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/distinct-until-changed), [RxJava](http://reactivex.io/documentation/operators/distinct), or [LiveData](/reference/androidx/lifecycle/Transformations#distinctUntilChanged(androidx.lifecycle.LiveData%3CX%3E)).\n\nAdditional resources\n--------------------\n\nTo learn more about asynchronous DAO queries, see the following additional\nresources:\n\n### Blogs\n\n- [Room \\& Flow](https://medium.com/androiddevelopers/room-flow-273acffe5b57)"]]