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

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

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

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

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

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

סוג השאילתה תכונות השפה של 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>

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

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

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

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

Java עם RxJava

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

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

Java עם LiveData ו-Guava

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

  • אפשר להשתמש ב-wrapper של LiveData מ-Jetpack לכתיבת שאילתות אסינכרוניות שניתנות לצפייה.
  • אפשר להשתמש ListenableFuture<T> wrapper מ-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 אסינכרוניות, אפשר לעיין במקורות הבאים משאבים:

דוגמיות

בלוגים