[android] Write asynchronous DAO queries - Room 에 대해 알아보자
-
UI 에서 query 하는 것을 막기 위해 room 은 main thread 에서 db 에 접근하는 것을 허락하지 않고 있다.
이 말은 DAO query 를 async 로 해야 한다는 것을 의미한다.
Room lib 은 async query 를 위해 여러개의 framework 를 통합시켰다.
-
DAO query 는 3개의 category 로 구분될 수 있다.
insert, update, delete 등의 one-shot write query
one-shot read query
observable read query
Language and framework options
-
One-shot write
Coroutines(suspend)
Single<T>, Maybe<T>, Completable
ListenableFuture<T>
One-shot read
Coroutines(suspend)
Single<T>, Maybe<T>
ListenableFuture<T>
Observable read
Flow<T>
Flowable<T>, Publisher<T>, Observable<T>
LiveData
* Kotlin with Flow and coroutines
-
Room 2.2 이상에서 Observable query 에 대해 Kotlin Flow 기능을 사용할 수 있다.
Room 2.1 이상에서 DAO query 에 suspend keyword 를 사용할 수 있다.
(Kotlin Flow 와 coroutine 을 room 과 함께 사용하려면 room-ktx dependency 를 정의해주는 것을 잊지 말자.)
* Java with RxJava
-
Room 2.1 에상에서 one-shot query 에 대해 Completable, Single<T>, Maybe<T> 를 return type 으로 지원한다.
Observable query 에 대해 Publisher<T>, Flowable<T>, Observable<T> 를 지원한다.
(RxJava 를 room 과 함께 사용하려면 room-rxjava2 dependency 를 정의해주는 것을 잊지 말자.)
* Java with LiveData and Guava
-
LiveData 와 ListenableFuture<T> 를 사용할 수 있다.
(Guava 를 room 과 함께 사용하려면 room-guava dependency 를 정의해주는 것을 잊지 말자.)
Write asynchronous one-shot queries
-
one-shot query 는 db 에 대해 1회 query 를 하고 그 snapshot 을 제공해주는 것을 이야기한다.
// Kotlin coroutine
@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>
}
// RxJava
@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);
}
Write observable queries
-
Observable query 는 table 에 변경이 생겼을 때마다 새로운 값을 전달해주는 read operation 을 이야기한다.
-
// Kotlin coroutines
@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>>
}
// RxJava
@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)
}
-
참고자료
https://developer.android.com/training/data-storage/room/async-queries