Room and RxJava
The classic reactive solution for Java is RxJava. RxJava 2 is the most popular version, and it offers a rich-but-complex set of types for reactive results delivery. Room, via the androidx.room:room-rxjava2
artifact, supports many of these, including Flowable
, Observable
, Single
, Maybe
, and Completable
. Or, we can use an alpha edition of androidx.room:room-rxjava3
, for RxJava 3, which debuted in 2020.
Your results-returning @Dao
functions might use something like Observable
or Maybe
, while your other @Dao
functions can use Completable
:
@Dao
interface Store {
@Query("SELECT * FROM todos")
fun all(): Observable<List<ToDoEntity>>
@Query("SELECT * FROM todos WHERE id = :modelId")
fun find(modelId: String): Maybe<ToDoEntity>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun save(vararg entities: ToDoEntity): Completable
@Delete
fun delete(vararg entities: ToDoEntity): Completable
}
Unlike with coroutines and LiveData
, Room has intermittent support for automatically putting your RxJava work on a scheduler with background threads. Room will put your Observable
work on its own scheduler, but not Maybe
or Completable
, for example. For those, you will need to supply your own scheduler, such as Schedulers.io()
:
package com.commonsware.todo.repo
import io.reactivex.Maybe
import io.reactivex.Observable
import io.reactivex.schedulers.Schedulers
class ToDoRepository(private val store: ToDoEntity.Store) {
fun items(): Observable<List<ToDoModel>> = store.all()
.map { all -> all.map { it.toModel() } }
fun find(id: String): Maybe<ToDoModel> = store.find(id)
.map { it.toModel() }
.subscribeOn(Schedulers.io())
fun save(model: ToDoModel) = store.save(ToDoEntity(model))
.subscribeOn(Schedulers.io())
fun delete(model: ToDoModel) = store.delete(ToDoEntity(model))
.subscribeOn(Schedulers.io())
}
Otherwise, you will get the “Cannot access database on the main thread” error.
Beyond that, though, you can then subscribe()
to these RxJava types and consume their results as you see fit.
Benefits of RxJava
RxJava is the most seasoned of these reactive solutions, so it is more likely that you will find information about any problems that you encounter.
Like coroutines, RxJava gives you flexibility for supplying a scheduler on which to observe the results. This is in contrast to LiveData
, which always delivers its results on the main application thread.
Issues with RxJava
RxJava has a very steep learning curve. Either LiveData
or coroutines will be simpler for newcomers to pick up and use.
Prev Table of Contents Next
This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.