تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
لمنع طلبات البحث من حظر واجهة المستخدم، لا تسمح Room بالوصول إلى قاعدة البيانات في
المسلسل الرئيسي. يعني هذا القيد أنّه عليك جعل طلبات بحث DAO غير متزامنة. تتضمّن مكتبة Room
عمليات دمج مع عدة إطارات عمل مختلفة لتوفير
تنفيذ الاستعلامات غير المتزامنة.
تندرج طلبات البحث عن البيانات الوصفية في ثلاث فئات:
طلبات بحث الكتابة لمرة واحدة التي تُدرج البيانات أو تعدّلها أو تحذفها في قاعدة البيانات
طلبات القراءة لمرة واحدة التي تقرأ البيانات من قاعدة بياناتك مرة واحدة فقط وتُعرِض
نتيجة تتضمّن نبذة عن قاعدة البيانات في ذلك الوقت
طلبات القراءة القابلة للتتبّع التي تقرأ البيانات من قاعدة بياناتك في كل مرة يتم فيها
تغيير جداول قاعدة البيانات الأساسية وتُصدِر قيمًا جديدة لتعكس
هذه التغيُّرات
خيارات اللغة والإطار
توفّر Room إمكانية الدمج للتشغيل التفاعلي مع ميزات مكتبات لغوية محدّدة. يعرض الجدول التالي أنواع النتائج السارية استنادًا
إلى نوع الاستعلام والإطار:
نوع طلب البحث
ميزات لغة Kotlin
RxJava
جوافة
مراحل النشاط في Jetpack
الكتابة لمرة واحدة
عمليات التشغيل المتعدّدة (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.
لغة Kotlin مع Flow وCoroutines
توفّر Kotlin ميزات لغوية تتيح لك كتابة طلبات بحث غير متزامنة
بدون استخدام إطارات عمل تابعة لجهات خارجية:
في الإصدار 2.2 من Room والإصدارات الأحدث، يمكنك استخدام وظائف Flow في Kotlin لكتابة طلبات بحث قابلة للتتبّع.
في الإصدار 2.1 من Room والإصدارات الأحدث، يمكنك استخدام الكلمة الرئيسية suspend لجعل طلبات بحث DAO
غير متزامنة باستخدام عمليات التنسيق المتعدّد في Kotlin.
Java مع RxJava
إذا كان تطبيقك يستخدم لغة برمجة Java، يمكنك استخدام أنواع مختصّة للقيمة المعروضة عند الرجوع
من إطار عمل RxJava لكتابة طرق DAO غير المتزامنة. يوفّر Room
دعمًا لأنواع النتائج التالية في RxJava 2:
بالنسبة إلى طلبات البحث لمرة واحدة، يتيح Room 2.1 والإصدارات الأحدث استخدام أنواع النتائج التالية:
Completable،
Single<T>،
وMaybe<T>.
بالإضافة إلى ذلك، يتوافق الإصدار 2.3 من Room والإصدارات الأحدث مع RxJava 3.
Java مع LiveData وGuava
إذا كان تطبيقك يستخدم لغة برمجة Java ولا تريد استخدام إطار عمل
RxJava، يمكنك استخدام البدائل التالية لكتابة طلبات بحث
غير المتزامنة:
يمكنك استخدام فئة LiveData wrapper
من Jetpack لكتابة طلبات بحث قابلة للتتبّع غير المتزامنة.
يمكنك استخدام ملف Wrapper الخاص بمجموعة أدوات برمجة Java
ListenableFuture<T>
من Guava لكتابة طلبات بحث غير متزامنة لمرة واحدة.
كتابة طلبات بحث لمرة واحدة غير متزامنة
طلبات البحث لمرة واحدة هي عمليات قاعدة بيانات يتم تنفيذها مرة واحدة فقط وتحصل على لقطة ملف شخصي
للبيانات في وقت التنفيذ. في ما يلي بعض الأمثلة على طلبات البحث غير المتزامنة
لمرة واحدة:
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);}
كتابة طلبات قابلة للتتبّع
الاستعلامات القابلة للتتبّع هي عمليات قراءة تُصدر قيمًا جديدة كلما حدثت
تغييرات في أيّ من الجداول التي يشير إليها الاستعلام. ومن الطرق التي يمكنك
استخدامها هذه الميزة هي مساعدتك في إبقاء قائمة معروضة بالعناصر محدّثة عند إدراج العناصر
في قاعدة البيانات الأساسية أو تعديلها أو إزالتها. في ما يلي بعض
أمثلة على طلبات البحث القابلة للتتبّع:
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);}
مصادر إضافية
لمزيد من المعلومات عن طلبات البحث غير المتزامنة في DAO، يُرجى الاطّلاع على المراجع التالية:
يخضع كل من المحتوى وعيّنات التعليمات البرمجية في هذه الصفحة للتراخيص الموضحّة في ترخيص استخدام المحتوى. إنّ Java وOpenJDK هما علامتان تجاريتان مسجَّلتان لشركة Oracle و/أو الشركات التابعة لها.
تاريخ التعديل الأخير: 2025-07-27 (حسب التوقيت العالمي المتفَّق عليه)
[[["يسهُل فهم المحتوى.","easyToUnderstand","thumb-up"],["ساعَدني المحتوى في حلّ مشكلتي.","solvedMyProblem","thumb-up"],["غير ذلك","otherUp","thumb-up"]],[["لا يحتوي على المعلومات التي أحتاج إليها.","missingTheInformationINeed","thumb-down"],["الخطوات معقدة للغاية / كثيرة جدًا.","tooComplicatedTooManySteps","thumb-down"],["المحتوى قديم.","outOfDate","thumb-down"],["ثمة مشكلة في الترجمة.","translationIssue","thumb-down"],["مشكلة في العيّنات / التعليمات البرمجية","samplesCodeIssue","thumb-down"],["غير ذلك","otherDown","thumb-down"]],["تاريخ التعديل الأخير: 2025-07-27 (حسب التوقيت العالمي المتفَّق عليه)"],[],[],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)"]]