Android

Exploring GreenDAO ORM database with Reactive RxJava in Android

As we have the basic understanding of RxJava features and functions from my last posts. I would be recommended that checking the all the post of Rx to better understanding this post. Here are some of the posts of understanding of Java 8 stream and Rx Observables, and basic understanding and practice features and functions of RxJava, and understanding practice RxJava with RxBinding in Android and understanding with Runtime Permission and RxPermmission.

RxJava is also very compatible with Kotlin also. If you developing an android application by using Kotlin then I would be recommended that check all post of Kotlin which are based on Reactive. Here is the posts details MVP design pattern by using Dagger2, Retrofit and Anko SQLite with RxJava. If you want to get deep digging about the Anko- SQLite then check this post-Anko SQLite database integration in Kotlin. and deep digging with API calls by Retrofit and RxJava in Kotlin.

Let’s start the exploring the GreenDao ORM database to integrate with RxJava in Android application. GreenDAO is a fast ORM (Object-Relational Mapping) tool for Android. GreenDAO offers an object-oriented interface with relation database SQLite. It is fast to other ORM that why it is something special and different. GreenDAO is work on two basic things. One is core Dao and another is Dao Generator. Only the first one is packed into your app and the second is only used for class generation (you won’t need or use it directly in your app). This is definitely something that makes GreenDAO so special.

For those who haven’t heard, this is a great open-source Android ORM solution which enables you to forget about SQLite low-level stuff and concentrate on the database’s overall life cycle, models and how do they relate. You don’t actually need to bother how to populate the database and how the relations work because greenDAO handles it for you. All you need to know is what you want to keep in your DB.

From the Offical Documentation of Green Dao, Let’s see all basic components of the GreenDao.

DaoMaster: DaoMaster holds the database object (SQLiteDatabase) and manages DAO classes (not objects) for a specific schema. It has static methods to create the tables or drop them. Its inner classes OpenHelper and DevOpenHelper are SQLiteOpenHelper implementations that create the schema in the SQLite database.

DaoSession: Manages all available DAO objects for a specific schema, which you can acquire using one of the getter methods. DaoSession provides also some generic persistence methods like insert, load, update, refresh and delete for entities. Lastly, a DaoSession object also keeps track of an identity scope.

DAOs: Data access objects (DAOs) persists and queries for entities. For each entity, GreenDAO generates a DAO. It has more persistence methods than DaoSession, for example, count, loadAll, and insertInTx.

Entities: Persistable objects. Usually, entities are objects representing a database row using standard Java properties (like a POJO or a JavaBean).

Ok, Let’s integrate the Green Dao database ORM in one of the demo application. Very first thing we need to add the relevant plugin and dependency in the gradle file. Basically, I am using with RxJava then we need to add the RxJava dependency also.

 compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
 compile 'io.reactivex.rxjava2:rxjava:2.0.8'

 compile 'org.greenrobot:greendao:3.2.0'
 compile 'net.zetetic:android-database-sqlcipher:3.5.1'
 apply plugin: 'org.greenrobot.greendao'

Now we need to add a Java Library Module for GreenDAO. So here I am creating new Module Java library name “greendaodb” and add the plugin in the gradle file.

 compile 'org.greenrobot:greendao-generator:3.2.0'

Let’s create the Entity for Dao main, which will create the database name and table with automated generated Dao files and Dao session. And make sure that you have given target directory in your gradle file to generate the Dao files there. GreenDAO also provides the table mapping very simple and easy way, for example, one-to-one , one-to-many or many-to-one. You get the detail from the official document for relational mapping.

greendao {
    targetGenDir 'src/main/java'
}
public class GreenDaoMain {

    public static void main(String[] args) throws Exception {
        Schema schema = new Schema(5, "com.sunil.mvp.db.model");
        addKickStarter(schema);
        new DaoGenerator().generateAll(schema, "../MVPAndroid/app/src/main/java/");
    }

    private static void addKickStarter(Schema schema) {
        Entity kickStarter = schema.addEntity("KickStarter");
        kickStarter.addIdProperty();
        kickStarter.addStringProperty("s_no").notNull();
        kickStarter.addStringProperty("amt_pledged");
        kickStarter.addStringProperty("blurb");
        kickStarter.addStringProperty("by");
        kickStarter.addStringProperty("country");
        kickStarter.addStringProperty("currency");
        kickStarter.addStringProperty("end_time");
        kickStarter.addStringProperty("location");
        kickStarter.addStringProperty("percentage");
        kickStarter.addStringProperty("num_backers");
        kickStarter.addStringProperty("state");
        kickStarter.addStringProperty("title");
        kickStarter.addStringProperty("type");
        kickStarter.addStringProperty("url");
    }
}

You should update the version number just to keep track of the updates. Also, we enable the keep sections, for the ability to modify our models without the fear that those modifications will be overridden by a next generation. It means When we required adding our custom methods or models inside the DAO we can add. But once we update the database version it will recreate all generated files again. In this case, our added custom method will be removed. So We should keep those methods or any thing we need to pointed out to DAO is to keep sections as it is while generating those Dao files again.

Security thing always on top of developing android application So GreenDAO provides the security feature which will be encrypted your database. Let’s implement the encrypted database.

public class GreenDaoDatabase {

    private static DaoSession mDaoSession;
    public static final boolean ENCRYPTED = true;

    private GreenDaoDatabase() {
    }

    private static class SingletonHolder {
        private static final GreenDaoDatabase INSTANCE = new GreenDaoDatabase();
    }

    public static GreenDaoDatabase getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public void init(Context context) {
        init(context, "db");
    }

    public void init(@NonNull Context context, @NonNull String dbName) {
        DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context.getApplicationContext(), ENCRYPTED ? "notes-db-encrypted" : "articles-db");
        Database db = ENCRYPTED ? helper.getEncryptedWritableDb("super-secret") : helper.getWritableDb();
        mDaoSession = new DaoMaster(db).newSession();
    }

    public DaoSession getDaoSession() {
        if (null == mDaoSession) {
            throw new NullPointerException("green db has not been initialized");
        }
        return mDaoSession;
    }
}

Ok, GreenDaoDatabse class is ready, Now you need to create the instance of this class in MainApplication class.

 GreenDaoDatabase.getInstance().init(this);

Let’s define the interface of all my operation wants to execute in our application, for example, insert data into a table and update the row of data or delete the row of the table. Here are the defined methods which I want to execute.

public interface KickStarterSource {
    Flowable<List<KickStarter>> getKickStarters();
    Observable<KickStarter> getKickStarterById(long rowId);
    void saveKickStarter(@NonNull KickStarter kickStarter);
    long getKickStartCount();
}

Ok, Let’s implement all operation with the Reactive feature.

public class KickStarterLocalSource implements KickStarterSource{

    private final  static String TAG = KickStarterLocalSource.class.getSimpleName();

     private KickStarterDao getKickStarterDao() {
        Timber.d(TAG, "getArticleDao()", Thread.currentThread().getName(), Thread.currentThread().getId());
        return GreenDaoDatabase.getInstance().getDaoSession().getKickStarterDao();
    }
    @Override
    public Flowable<List<KickStarter>> getKickStarters() {
        return Flowable.fromCallable(new Callable<List<KickStarter>>() {
            @Override
            public List<KickStarter> call() throws Exception {
                Timber.d(TAG, "getKickStarters()", Thread.currentThread().getName(), Thread.currentThread().getId());
                List<KickStarter> list = getKickStarterDao().loadAll();
                Timber.d("getKickStarters: " + list.size());
                return list;
            }
        });
    }

    @Override
    public Observable<KickStarter> getKickStarterById(final long rowId) {
        return Observable.fromCallable(new Callable<KickStarter>() {
            @Override
            public KickStarter call() throws Exception {
                Timber.d(TAG, "getKickStarterById()", Thread.currentThread().getName(), Thread.currentThread().getId());
                KickStarter kickStarter = getKickStarterDao().load(rowId);
                return kickStarter;
            }

        });
    }

    @Override
    public void saveKickStarter(@NonNull KickStarter kickStarter) {
        Timber.d(TAG, "saveKickStarter()", Thread.currentThread().getName(), Thread.currentThread().getId());
        getKickStarterDao().insertOrReplace(kickStarter);

    }
}

Let’s call one of the methods executes the load operation.

 private void loadFromDb(){
        Flowable<List<KickStarter>> listFlowable = mKickStarterLocalDataSource.getKickStarters();
        listFlowable.doOnSubscribe(new Consumer<Subscription>() {
            @Override
            public void accept(@io.reactivex.annotations.NonNull Subscription subscription) throws Exception {

            }
        }).subscribe(new Consumer<List<KickStarter>>() {
            @Override
            public void accept(@io.reactivex.annotations.NonNull List<KickStarter> kickStarters) throws Exception {
                mKickStartView.onKickStartersOk(kickStarters);
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(@io.reactivex.annotations.NonNull Throwable throwable) throws Exception {
                Preconditions.checkNotNull(throwable);
                mKickStartView.showLoadErrorMessage(throwable.getMessage());
            }
        }, new Action() {
            @Override
            public void run() throws Exception {
                // mKickStartView.onLoadFinish();
            }
        });
    }

That’s it! We have successfully integrated GreenDAO into our Android application! If you would like to add other tables, go to the generator class, edit the entities, and run the generator class. This will generate the DAO files and other entities needed.

Wrapping Up: GreenDAO is one of the many Android ORM database libraries available. What makes it stand out is its performance and advanced caching support. It’s being actively developed and new features are added with each new release.  You can get the full source code from Github.

If you wondering Kotlin for android then I would be recommended to check all this post of Kotlin Category.

Please do subscribe your email to get every newsletter from this blog and if you feel that this post helps you then do not forget to share and comment below.

Happy coding 🙂

0 0 votes
Article Rating

Recent Posts

Hide your production API key or any sensitive data in Android

Hi everyone, In this article, we are going to learn how to hide the production… Read More

2 years ago

How to handle the localisation or multi language support in android with examples?

Hello everyone, Today in this article, we are going to learn about localisation to support… Read More

2 years ago

How to convert any callback to Coroutines and use them in Kotlin Android?

Hello everyone, In this article, we are going to learn something to handle the callback… Read More

2 years ago

Request Permission Launcher with Kotlin in Android

In this article, we are learning about the run time permissions for request permission launchers.… Read More

2 years ago

Implement the SMS User Consent API and SMS Retriever API in Android

Hello everyone. In my last tutorial, we learned about the Jetpack Compose introduction and about applying the… Read More

3 years ago

Jetpack Compose Coroutine flow with LiveData/ViewModel in Android

Hello everyone, In this article, we are going to learn about the Jetpack Compose with… Read More

3 years ago