เขียนคำค้นหา DAO แบบไม่พร้อมกัน

Room ไม่อนุญาตให้เข้าถึงฐานข้อมูลในเธรดหลักเพื่อป้องกันไม่ให้การค้นหาบล็อก UI ข้อจํากัดนี้หมายความว่าคุณต้องทําให้การค้นหา DAO เป็นแบบไม่พร้อมกัน ห้องสมุด Room มีการผสานรวมกับเฟรมเวิร์กต่างๆ เพื่อดำเนินการค้นหาแบบไม่พร้อมกัน

การค้นหา DAO แบ่งออกเป็น 3 หมวดหมู่ ดังนี้

  • การค้นหาการเขียนแบบครั้งเดียวที่แทรก อัปเดต หรือลบข้อมูลในฐานข้อมูล
  • การค้นหาแบบอ่านครั้งเดียวซึ่งอ่านข้อมูลจากฐานข้อมูลเพียงครั้งเดียวและแสดงผลลัพธ์ที่มีสแนปชอตของฐานข้อมูล ณ ขณะนั้น
  • การค้นหาการอ่านที่สังเกตได้ซึ่งอ่านข้อมูลจากฐานข้อมูลทุกครั้งที่ตารางฐานข้อมูลที่สําคัญมีการเปลี่ยนแปลงและแสดงค่าใหม่เพื่อแสดงการเปลี่ยนแปลงเหล่านั้น

ตัวเลือกภาษาและเฟรมเวิร์ก

Room รองรับการผสานรวมเพื่อการทำงานร่วมกันกับฟีเจอร์และไลบรารีภาษาที่เฉพาะเจาะจง ตารางต่อไปนี้แสดงประเภทผลลัพธ์ที่เกี่ยวข้องตามประเภทการค้นหาและเฟรมเวิร์ก

ประเภทคำค้นหา ฟีเจอร์ภาษา Kotlin RxJava ชมพูกวาวา วงจรของ Jetpack
การเขียนแบบเขียนครั้งเดียว Coroutine (suspend) Single<T>, Maybe<T>, Completable ListenableFuture<T> ไม่มี
การอ่านแบบครั้งเดียว Coroutine (suspend) Single<T>, Maybe<T> ListenableFuture<T> ไม่มี
การอ่านที่สังเกตได้ Flow<T> Flowable<T>, Publisher<T>, Observable<T> ไม่มี LiveData<T>

คู่มือนี้แสดงวิธี 3 วิธีที่คุณสามารถใช้การผสานรวมเหล่านี้เพื่อใช้การค้นหาแบบไม่พร้อมกันใน DAO

Kotlin ที่มี Flow และโคโรอูติน

Kotlin มีฟีเจอร์ภาษาที่ช่วยให้คุณเขียนการค้นหาแบบไม่พร้อมกันได้โดยไม่ต้องใช้เฟรมเวิร์กของบุคคลที่สาม

  • ใน Room 2.2 ขึ้นไป คุณสามารถใช้ฟังก์ชัน Flow ของ Kotlin เพื่อเขียนการค้นหาที่สังเกตได้
  • ใน Room 2.1 ขึ้นไป คุณสามารถใช้คีย์เวิร์ด suspend เพื่อทําให้การค้นหา DAO เป็นแบบไม่พร้อมกันโดยใช้ Kotlin coroutines

Java พร้อม RxJava

หากแอปใช้ภาษาโปรแกรม Java คุณสามารถใช้ประเภทผลลัพธ์เฉพาะจากเฟรมเวิร์ก RxJava เพื่อเขียนเมธอด DAO แบบแอซิงโครนัส Room รองรับประเภทผลลัพธ์ RxJava 2 ต่อไปนี้

  • สําหรับการค้นหาแบบครั้งเดียว Room 2.1 ขึ้นไปรองรับประเภทผลลัพธ์ Completable, Single<T> และ Maybe<T>
  • สําหรับการค้นหาที่สังเกตได้ Room รองรับประเภทผลลัพธ์ Publisher<T>, Flowable<T> และ Observable<T>

นอกจากนี้ Room 2.3 ขึ้นไปยังรองรับ RxJava 3 ด้วย

Java ที่มี LiveData และ Guava

หากแอปใช้ภาษาโปรแกรม Java และไม่ต้องการเฟรมเวิร์ก RxJava คุณสามารถใช้ทางเลือกต่อไปนี้ในการเขียนการค้นหาแบบไม่พร้อมกัน

  • คุณสามารถใช้คลาส Wrapper LiveData จาก Jetpack เพื่อเขียนการค้นหาแบบสังเกตการณ์แบบแอซิงโครนัส
  • คุณสามารถใช้ Wrapper ของ 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 แบบไม่พร้อมกันได้ที่แหล่งข้อมูลเพิ่มเติมต่อไปนี้

บล็อก