Menulis kueri DAO asinkron

Untuk mencegah kueri memblokir UI, Room tidak mengizinkan akses database pada thread utama. Batasan ini berarti Anda harus membuat kueri DAO secara asinkron. Library Room menyertakan integrasi dengan beberapa framework berbeda untuk menyediakan eksekusi kueri asinkron.

Kueri DAO dibagi menjadi tiga kategori:

  • Kueri tindakan tulis satu kali yang menyisipkan, memperbarui, atau menghapus data dalam database.
  • Kueri tindakan baca satu kali yang membaca data dari database Anda hanya sekali dan menampilkan hasil beserta rekaman data dari database pada saat itu.
  • Kueri tindakan baca yang dapat diamati yang membaca data dari database Anda setiap kali tabel database pokok berubah dan memunculkan nilai baru untuk mencerminkan perubahan tersebut.

Opsi bahasa dan framework

Room memberikan dukungan integrasi untuk interoperabilitas dengan library dan fitur bahasa tertentu. Tabel berikut menampilkan jenis nilai yang ditampilkan, yang dapat diterapkan berdasarkan jenis kueri dan framework:

Jenis kueri Fitur bahasa Kotlin RxJava Guava Siklus Proses Jetpack
Tindakan tulis satu kali Coroutine (suspend) Single<T>, Maybe<T>, Completable ListenableFuture<T> T/A
Tindakan baca satu kali Coroutine (suspend) Single<T>, Maybe<T> ListenableFuture<T> T/A
Tindakan baca yang dapat diamati Flow<T> Flowable<T>, Publisher<T>, Observable<T> T/A LiveData<T>

Panduan ini menunjukkan tiga kemungkinan cara menggunakan integrasi tersebut untuk mengimplementasikan kueri asinkron di DAO.

Kotlin dengan Flow dan couroutine

Kotlin menyediakan fitur bahasa yang memungkinkan Anda menulis kueri asinkron tanpa framework pihak ketiga:

  • Di Room 2.2 dan yang lebih tinggi, Anda dapat menggunakan fungsi Flow Kotlin untuk menulis kueri tindakan yang dapat diamati.
  • Di Room 2.1 dan lebih tinggi, Anda dapat menggunakan kata kunci suspend untuk membuat kueri DAO menjadi asinkron menggunakan coroutine Kotlin.

Java dengan RxJava

Jika aplikasi menggunakan bahasa pemrograman Java, Anda dapat menggunakan jenis nilai yang ditampilkan khusus dari framework RxJava untuk menulis metode DAO asinkron. Room memberikan dukungan untuk jenis nilai yang ditampilkan RxJava 2 berikut:

Selain itu, Room 2.3 dan yang lebih tinggi juga mendukung RxJava 3.

Java dengan LiveData dan Guava

Jika aplikasi menggunakan bahasa pemrograman Java dan Anda tidak ingin menggunakan framework RxJava, Anda dapat menggunakan alternatif berikut untuk menulis kueri asinkron:

  • Anda dapat menggunakan class wrapper LiveData dari Jetpack untuk menulis kueri asinkron tindakan yang dapat diamati.
  • Anda dapat menggunakan wrapper ListenableFuture<T> dari Guava untuk menulis kueri tindakan satu kali asinkron.

Menulis kueri satu kali asinkron

Kueri tindakan satu kali adalah operasi database yang hanya berjalan sekali dan mengambil rekaman data pada saat eksekusi. Berikut beberapa contoh kueri satu kali asinkron:

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

Menulis kueri yang dapat diamati

Kueri yang dapat diamati adalah operasi baca yang memunculkan nilai baru setiap kali ada perubahan pada tabel yang dirujuk oleh kueri. Salah satu manfaatnya adalah untuk membantu terus memperbarui daftar item yang ditampilkan saat item dalam database pokok disisipkan, diperbarui, atau dihapus. Berikut beberapa contoh kueri yang dapat diamati:

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

Referensi lainnya

Untuk mempelajari kueri DAO asinkron lebih lanjut, lihat referensi tambahan berikut:

Blog