Room. Reactive queries

Integrating LiveData with Room

Room has great integration with LiveData. Results from SQL queries can be easily wrapped in LiveData container. This way LiveData can be observed in the UI. When the data is changed in the database, all active observers get notified and update the corresponding views. This saves time for writing plenty lines of code for updating all the views containing database data every time database change is triggered.
In the CoinDao we have the getHistoricalData() method which returns all the available records specified by the cryptoCurrency parameter. Room maps the records to the Coin class and returns a List of coins.
@Query("SELECT * FROM Coin WHERE cryptoCurrency = :cryptoCurrency")
    List<Coin> getHistoricalData(String cryptoCurrency);
The next step is to wrap the List in LiveData container. And it is easy as it sounds. Just add the LiveData<> wrapper around the List as shown below.
@Query("SELECT * FROM Coin WHERE cryptoCurrency = :cryptoCurrency")
    LiveData<List<Coin>> getHistoricalData(String cryptoCurrency);
We create a view model called LineChartViewModel which will be responsible for handling business logic – in our case returning data saved in the database. The specifics of the view model in Android were observed in the “View model example” tutorial so we will not go in depths in this tutorial. The code below represents the LineChartViewModel class. It can be seen that an instance of CoinDao class is created in the class constructor (Room implements the CoinDao interface in terms of methods that we have defined). Then in the getHistoricalData() method is called the corresponding method from CoinDao. CoinDao‘s getHistoricalData() method makes a database call and returns all records saved in the database. The records are wrapped in an observable LiveData holder and can be consumed in all views (Activities or Fragments) which have subscribed for the event (observe the LiveData container).
public class LineChartViewModel extends ViewModel {

    private CoinDao mCoinDao;

    private String cryptoCurrency = "BITCOIN";

    public LineChartViewModel() {
        mCoinDao = CryptoDatabase.getInstance().coinDao();

    public LiveData<List<Coin>> getHistoricalData() {
        return mCoinDao.getHistoricalData(cryptoCurrency);
Then we create a LineChartViewModel instance in the LineChartActivity used for observing LiveData objects which are positioned in the ViewModel of the activity. For getting instance of the ViewModel we use the ViewModelProviders class and we call the of() method passing the lifecycle owner (in this case this refers to LineChartActivity.class). With the get() method we specify which ViewModel class we are going to use for this activity.
public class LineChartActivity extends AppCompatActivity {

    private LineChartViewModel mLineChartViewModel;
mLineChartViewModel = ViewModelProviders.of(this).get(LineChartViewModel.class);
Then we call the getHistoricalData() from the LineChartViewModel which in turn calls the getHistoricalData() defined in the CoinDao. The result of the method execution is LiveData, which is observed by calling the observe() method and passing two parameters to it. The first one is the lifecycle owner of the ViewModel (in this case this refers to LineChartActivity.class) and the second parameter is a lambda expression. The lambda expression is a short way of expressing the idea: “when a data change occurs in the LiveData container, then give me the changed data for visualization in the UI”. On each data change event the drawChart() method is called for redrawing the chart with the newest available data.
mLineChartViewModel.getHistoricalData().observe(this, coins -> {
            if(coins != null) {
                if(coins.size() > 0) {
Another great thing about LiveData is that when the getHistoricalData() call is made to the CoinDao, the execution of the database call is asynchronous and it is executed on a background thread. The execution of long running tasks on a background thread is essential for mobile applications. This way the UI is not blocked and the user can continue using the application, which results in higher user experience.