Room implementation with RxJava

MOHD SAQUIB
MindOrks
Published in
5 min readFeb 28, 2019
Image Source

As we know Room is a persistence library from the architecture component introduced by Google and most of the developer has already migrated their local storage implementation into Room from SQLite. In fact, Room is a persistence library which provides an abstract layer over SQLite to allow for more robust database access while harnessing the full power of SQLite. I am assuming that all of you are aware of the implementation of the Room Library. So not going deep into its basic. In case you are new to Room then refer to the link given below.

We have some doubts during the implementation of Room that room Query return only LiveData object to observe the data from our database. Whenever there will be any changes we can observe that efficiently and easily. Most of the developer gets confused on the Query return type in Room but as the document says there are 3 types of queries supported in Query methods: SELECT, UPDATE and DELETE.

For SELECT queries, Room will infer the result contents from the method’s return type and generate the code that will automatically convert the query result into the method’s return type. For single result queries, the return type can be any Java object. For queries that return multiple values, you can use List or Array. In addition to these, any query may return Cursor or any query result can be wrapped in a LiveData.

The queries returning LiveData allow you to get automatic updates whenever the data changes to make sure your UI changes as per the latest data from your database. Now the question comes in our mind if we are not using LiveData, can we observe the changes automatically whenever any update/insert take place in our database?
Yes, definitely you can do by using RxJava 2. If you are working with Rxjava 2 then there are few observables like Maybe, Single, and Flowable which can be used with Room. Room also supports Observable from`2.0.0-beta01`. Till the end of the article, you will understand which observable behave the almost same as LiveData, so we will cover each scenario for better understanding the use.

Let's understand the implementation part:

@Query("select * from SaquibTable")
List<ModelClass> getItemList();

If you will just return List<ModelClass> then there will be two drawbacks one is that It is blocking and is a synchronous call and another one you will have to call getItemList() each time if you made changes in your database like insertion/deletion etc. So what we will do we will use RxJava observables to observe changes every time automatically.

To provide RxJava support for Room just add this dependency to your Gradle file.

implementation “android.arch.persistence.room:rxjava2:1.1.1”

Let me just show you code implementation so that it will be easy to understand the actual scenario. Here is Dao class implementation.

@Dao
public interface BrowseDataClass {

@Query("select * from SaquibTable")
Flowable<List<ModelClass>> getItemList();

@Insert
long addData(ModelClass modelClass);

}

getItemList() method is used to get the user from the database, we could write the following query in the data access object class.

@Query("select * from SaquibTable")
Flowable<List<ModelClass>> getItemList();

We will call getItemList() from our ViewModel class, so let us have a look of ViewModel. Now, have a quick look at our getList() method inside ViewModel which will call from activity/fragment and it returns Flowable which will be observed inside our activity/fragment.

public class RoomWithRxJavaViewModel extends AndroidViewModel {

private MyDataBase appDatabase;

public RoomWithRxJavaViewModel(@NonNull Application application) {
super(application);
appDatabase = MyDataBase.getDatabase(application);
}

Flowable<List<ModelClass>> getList() {
return appDatabase.courseAndNameModel().getItemList();
}

long addData(ModelClass modelClass) {
return appDatabase.courseAndNameModel().addData(modelClass);
}

}

Where MyDataBase class is as below:

@Database(entities = {ModelClass.class}, version = 1)
public abstract class MyDataBase extends RoomDatabase {

private static MyDataBase instance;

static MyDataBase getDatabase(Context context) {
if (instance == null) {
instance = Room.databaseBuilder(context, MyDataBase.class, "your_db_name").build();
}
return instance;
}


public abstract BrowseDataClass courseAndNameModel();

}

So these were basic implementation now the main thing how we are using these classes/methods in our View(Activity/Fragment).

Let us see how we will code into our Activity to observe the changes and consume changed data.

viewModel.getList().subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(modelClasses ->
{
//consume modelClasses here which is a list of ModelClass
System.out.println("RoomWithRx: " + modelClasses.size());

}, e -> System.out.println("RoomWithRx: " +e.getMessage()));

We will only observe getList() method once in onCreate() and every time you will add/delete/update in the database automatically you will get updated data to consume it. Suppose you are adding a modelClass object into your database by calling

@Insert
long addData(ModelClass modelClass);

as our modelClass object inserts into DB then automatically new changes will be observed using viewModel.getList() inside onCreate() method of activity which I have shown earlier.
We can also use Maybe and Single observables instead of Flowable but there is a lot of difference in all observables. Let us see one by one.

Maybe:

@Query("select * from SaquibTable")
Maybe<List<ModelClass>> getItemList();

When we observe method from Dao class which For queries return Maybe few points is important to note down that…

“If there is not any data in your database and the query return no row Maybe will complete.”
“When there is already an entry of ModelClass object in your database, Maybe will trigger onSuccess and it will complete.”
“Now if again you add new data or update your previous inserted object then nothing happens if Maybe is already completed.”

Single:

@Query("select * from SaquibTable")
Single<List<ModelClass>> getItemList();

When we observe method from Dao class which For queries return Single few points is important to note down that…

If there is not any data in your database and the query return no row Single will trigger onError(EmptyResultSetException.class).
When there is already an entry of ModelClass object in your database, Single will trigger onSuccess.”
Now if again you add new data or update your previous inserted object then nothing happens if Single is already completed.

For queries that return Maybe or Single, make sure you’re calling subscribeOn with a different Scheduler than AndroidSchedulers.mainThread().

Flowable:
In case of a query that returning Flowable as I show earlier in the code implementation, the behavior is quite good and a replacement of LiveData in some aspect.

Here is how Flowable behaves:
If there is not any data in your database and the query return no row the Flowable will not emit, neither onNext, nor onError.
When there is already an entry of ModelClass object in your database, Flowable will trigger onNext.”
Now if again you add new data or update your previous inserted object then the Flowable object will emit automatically, allowing you to update the UI based on the latest data.

Note: Observable behavior is same as Flowable and Room supports Observable from`2.0.0-beta01`.

If you’re worried about threads, Room ensures you that observable queries are done off the main thread. It depends upon you that how you are deciding on which thread the events are emitted downstream, by setting the Scheduler in the ObserveOn method.

Give a clap if you like the article and Let’s become friends on Linkedin and Facebook.

Happy Coding…
Thanks & Regards

--

--