livedata (1)


Flowable from Room database

Hi! Today I’ll tell you how to get data from Room database in reactive way.

Before starting make sure you have following in your build.gradel:

// Room components
implementation "android.arch.persistence.room:runtime:$rootProject.roomVersion"
implementation "android.arch.persistence.room:rxjava2:$rootProject.roomVersion"
annotationProcessor "android.arch.persistence.room:compiler:$rootProject.roomVersion"
androidTestImplementation "android.arch.persistence.room:testing:$rootProject.roomVersion"

// Lifecycle components
implementation "android.arch.lifecycle:extensions:$rootProject.archLifecycleVersion"
implementation "android.arch.lifecycle:reactivestreams:$rootProject.archLifecycleVersion"
annotationProcessor "android.arch.lifecycle:compiler:$rootProject.archLifecycleVersion"

// Rx
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation 'io.reactivex.rxjava2:rxjava:2.2.1'

First we need to get database from assets and define Dao class for data.

@Database(entities = {Verse.class}, version = 1, exportSchema = false)
public abstract class MyRoomDatabase extends RoomDatabase {
    public abstract MyDataDao myDataDao();

    private static MyRoomDatabase INSTANCE;

    static MyRoomDatabase getDatabase(final Context context) {
        if (INSTANCE == null) {
            synchronized (MyRoomDatabase.class) {
                if (INSTANCE == null) {
                    INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                            MyRoomDatabase.class, "data.sqlite3") // get db from assets
                            .openHelperFactory(new AssetSQLiteOpenHelperFactory())
                            .build();

                }
            }
        }
        return INSTANCE;
    }

    public void destroyInstance() {
        synchronized (MyRoomDatabase.class) {
            INSTANCE = null;
        }
    }
}

@Dao
public interface MyDataDao {

    @Query("SELECT * from verses ORDER BY RANDOM() LIMIT 1")
    LiveData<Verse> getRandomVerse();

    @Query("SELECT * from verses ORDER BY RANDOM() LIMIT 1")
        // same request
    Flowable<Verse> getRxRandomVerse();
}

Above code represents raw request for random Verse objects from database table verses
What I like about Room is it allows us to get Rx Flowable as well as LiveData objects out of the box!
In our case we will use Flowable.
Next, define a repository class:

class MyRepository(context: Context?) {

    private val mDataDao: MyDataDao
    private val db: MyRoomDatabase? = MyRoomDatabase.getDatabase(context)

    init {
        mDataDao = db!!.myDataDao()
    }

    fun getRxRandomVerse(): Flowable<Verse> {
        return mDataDao.getRxRandomVerse
    }

    fun getDb(context: Context?): MyRoomDatabase? {
        return db ?: MyRoomDatabase.getDatabase(context)
    }

    fun closeDb() {
        db?.close()
    }
}

Finally, let’s extract data onto presentation layer:

class MainActivityPresenter {

    private var mRepository: MyRepository? = null

    fun attach(mainActivityView: MainActivityView, context: Context) {
        this.mainActivityView = mainActivityView
        this.mRepository = MyRepository(context)
    }

    fun getRandomVerse() {
        mainActivityView!!.showProgressBar()
        mRepository.getRxRandomVerse()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ verse ->
                    mainActivityView!!.hideProgressBar()
                    updateUI(verse?.toString())
                }, { error ->
                    mainActivityView!!.hideProgressBar()
                    error.printStackTrace()
                })
    }
}

class MainActivity : MainActivityPresenter.MainActivityView {

    ...

    override fun updateUI(verse: String) {
        textViewVerse.text = verse
    }

    ...
}

That’s all in general. Pretty simple and handy. I’ve successfully implemented this code in a new random quote app

If you have any questions, leave in comments below.