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 แบบไม่พร้อมกันได้ที่แหล่งข้อมูลเพิ่มเติมต่อไปนี้