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.