Room and RxJava
A normal Dao
@Query(“SELECT * FROM Users WHERE id = :userId”)
User getUserById(String userId);
This has two disadvantages:
- Code is blocking, synchronous call
- Must manually call method everytime user data is changed
We can fix this with RxJava by returning a Maybe
, Single
, or Flowable
object to make the call asynchronous and observable.
For queries that return Maybe
or Single
, make sure you’re calling subscribeOn
with a different Scheduler than AndroidSchedulers.mainThread()
.
Build.gradle
// RxJava support for Room
implementation “android.arch.persistence.room:rxjava2:1.0.0-alpha5”
// Testing support
androidTestImplementation “android.arch.core:core-testing:1.0.0-alpha5”
Maybe
@Query(“SELECT * FROM Users WHERE id = :userId”)
Maybe<User> getUserById(String userId);
Single
@Query(“SELECT * FROM Users WHERE id = :userId”)
Single<User> getUserById(String userId);
Flowable
@Query(“SELECT * FROM Users WHERE id = :userId”)
Flowable<User> getUserById(String userId);
Testing
@RunWith(AndroidJUnit4.class)
public class UserDaoTest {
@Rule
public InstantTaskExecutorRule instantTaskExecutorRule =
new InstantTaskExecutorRule();
…
private UsersDatabase mDatabase;
@Before
public void initDb() throws Exception {
mDatabase = Room.inMemoryDatabaseBuilder(
InstrumentationRegistry.getContext(),
UsersDatabase.class)
// allowing main thread queries, just for testing
.allowMainThreadQueries()
.build();
}
@After
public void closeDb() throws Exception {
mDatabase.close();
}
@Test
public void insertAndGetUserById() {
// Given that we have a user in the data source
mDatabase.userDao().insertUser(USER);
// When subscribing to the emissions of user
mDatabase.userDao()
.getUserById(USER.getId())
.test()
// assertValue asserts that there was only one emission
.assertValue(new Predicate<User>() {
@Override
public boolean test(User user) throws Exception {
// The emitted user is the expected one
return user.getId().equals(USER.getId()) &&
user.getUserName().equals(USER.getUserName());
}
});
}