كتابة طلبات بحث DAO غير المتزامنة

لمنع طلبات البحث من حظر واجهة المستخدم، لا تسمح 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>.
  • بالنسبة إلى طلبات البحث القابلة للتتبّع، تتيح Room أنواع عرض ملف السجلّ التالية: Publisher<T>، Flowable<T>، وObservable<T>.

بالإضافة إلى ذلك، يتوافق الإصدار 2.3 من Room والإصدارات الأحدث مع RxJava 3.

Java مع LiveData وGuava

إذا كان تطبيقك يستخدم لغة برمجة Java ولا تريد استخدام إطار عمل RxJava، يمكنك استخدام البدائل التالية لكتابة طلبات بحث غير المتزامنة:

  • يمكنك استخدام فئة LiveData wrapper من Jetpack لكتابة طلبات بحث قابلة للتتبّع غير المتزامنة.
  • يمكنك استخدام ملف Wrapper الخاص بمجموعة أدوات برمجة Java ListenableFuture<T> من Guava لكتابة طلبات بحث غير متزامنة لمرة واحدة.

كتابة طلبات بحث لمرة واحدة غير متزامنة

طلبات البحث لمرة واحدة هي عمليات قاعدة بيانات يتم تنفيذها مرة واحدة فقط وتحصل على لقطة ملف شخصي للبيانات في وقت التنفيذ. في ما يلي بعض الأمثلة على طلبات البحث غير المتزامنة لمرة واحدة:

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);
}

كتابة طلبات قابلة للتتبّع

الاستعلامات القابلة للتتبّع هي عمليات قراءة تُصدر قيمًا جديدة كلما حدثت تغييرات في أيّ من الجداول التي يشير إليها الاستعلام. ومن الطرق التي يمكنك استخدامها هذه الميزة هي مساعدتك في إبقاء قائمة معروضة بالعناصر محدّثة عند إدراج العناصر في قاعدة البيانات الأساسية أو تعديلها أو إزالتها. في ما يلي بعض أمثلة على طلبات البحث القابلة للتتبّع:

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);
}

مصادر إضافية

لمزيد من المعلومات عن طلبات البحث غير المتزامنة في DAO، يُرجى الاطّلاع على المراجع التالية:

المدوّنات