כתיבת שאילתות DAO אסינכרוניות

כדי למנוע משאילתות לחסום את ממשק המשתמש, אפליקציית Room לא מאפשרת גישה למסד נתונים בשרשור הראשי. המשמעות של ההגבלה הזו היא שאתם צריכים לבצע את הפעולות הבאות: DAO שאילתות אסינכרוניות. החדר כוללת שילובים עם כמה מסגרות שונות כדי לספק ביצוע שאילתה אסינכרונית.

שאילתות DAO מחולקות לשלוש קטגוריות:

  • שאילתות כתיבה מדוגמה אחת שמוסיפה, מעדכנות או מוחקים נתונים למסד הנתונים.
  • שאילתות קריאה חד-פעמית שקוראות נתונים מהמסד נתונים רק פעם אחת ומחזירות תוצאה עם תמונת המצב של המסד נתונים באותו זמן.
  • שאילתות קריאה שניתנת לצפייה שקוראות נתונים ממסד הנתונים שלכם בכל פעם בטבלאות של מסדי הנתונים הבסיסיים משתנים ופולטים ערכים חדשים שישקפו אותם שינויים.

אפשרויות שפה ומסגרות

חדר כולל תמיכה בשילוב ליכולת פעולה הדדית עם שפה ספציפית חדשות וספריות. בטבלה הבאה מפורטים הסוגים הרלוונטיים של החזרת מוצרים, לפי לפי סוג השאילתה והמסגרת:

סוג השאילתה תכונות של שפת Kotlin RxJava גויאבה Jetpack Lifecycle
כתיבה מהירה קורוטינים (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>

במדריך הזה מוצגות שלוש דרכים אפשריות לשימוש בשילובים האלה כדי להטמיע שאילתות אסינכרוניות ב-DAOs.

קוטלין עם זרימה וקורטינים

Kotlin עם תכונות שפה שמאפשרות לכתוב שאילתות אסינכרוניות ללא מסגרות של צד שלישי:

  • בחדר 2.2 ואילך אפשר להשתמש ב-Kotlin זרימה לכתיבת שאילתות שניתנות למדידה.
  • בחדר 2.1 ואילך, ניתן להשתמש במילת המפתח suspend כדי ליצור את DAO של שאילתות אסינכרוניות באמצעות קורוטינים של Kotlin.

Java עם RxJava

אם באפליקציה שלכם נעשה שימוש בשפת התכנות Java, תוכלו להשתמש בסוגי החזרה מיוחדים מהמסגרת RxJava כדי לכתוב שיטות DAO אסינכרוניות. ב-Room יש תמיכה בסוגי ההחזרים הבאים של RxJava 2:

בנוסף, Room 2.3 ואילך תומך ב-RxJava 3.

Java עם LiveData ו-Guava

אם האפליקציה שלכם משתמשת בשפת התכנות Java ואתם לא רוצים להשתמש במסגרת RxJava, אפשר להשתמש בחלופות הבאות כדי לכתוב אסינכרונית שאילתות:

  • אפשר להשתמש ב-wrapper של LiveData מ-Jetpack לכתיבת שאילתות אסינכרוניות שניתנות לצפייה.
  • אפשר להשתמש ListenableFuture<T> wrapper מ-Guava לכתיבת שאילתות אסינכרוניות חד-פעמיות.

כתיבת שאילתות אסינכרוניות עם דוגמה אחת

שאילתות חד-פעמיות הן פעולות במסד נתונים שפועלות רק פעם אחת ומפיקות קובץ snapshot של הנתונים בזמן הביצוע. ריכזנו כאן כמה דוגמאות לשאילתות חד-פעמיות אסינכרניות:

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 אסינכרוניות, אפשר לעיין במקורות הבאים משאבים:

דוגמיות

בלוגים