Category: Blog, Android, Development

Example of Realm with MVP and Dagger

Example of Realm with MVP and Dagger

More and more complicated

In my previous article I’ve shown you a simple example of how to use Realm database. However projects that we are working on are definitely more complicated. We use different libraries like ButterKnife, EventBus, Retrofit, Dagger and so on. We also try to make our app more testable i.e. with the use of MVP pattern. All these things should make our life easier, sure, but it’s not that obvious how to implement it correctly – especially for the first time. In below example I tried to use Realm database in app with MVP architecture and Dagger library.

Functionalities

What the app can do?

  1. List all books.
  2. Add new book.
  3. Show book’s details.
  4. Show all publisher’s books.
  5. Show all author’s books.

Model

Model consists of three simple classes.

Using Realm

According to the documentation:

This means that on the UI thread the easiest and safest approach is to open a Realm instance in all your Activities and Fragments and close it again when the Activity or Fragment is destroyed.

That’s what we’ll do with Dagger and MVP.

Dagger

I used Dagger, among others, to get Realm instance for each Activity. First of all Realm configuration was initialized in Application class in initRealmConfiguration() method.

Next thing is to provide Realm instance.

Now we are ready to provide Realm instance to each Activity. ApplicationModule also provides RealmService object but about that later.

MVP

With the use of MVP pattern we try to make our views like Jon Snow – they should know nothing. Views should take care only to show something on screen or get taps and pass them on. Without ‘thinking’ and any logic. So views shouldn’t know about Realm instance either. We have to pass Realm instance to Presenter but dealing with database directly in it could be a huge burden. RealmService solves the problem.

The code of BooksActivity is shown below.

What that code is doing?

  • Initialize adapter and RecyclerView in initList().
  • Manage the View in presenter in onStart() and onStop().
  • Show books in showBooks(…).
  • Get taps in onBookClick(…) and onAddNewBookClick().
  • Go to another views in showBookDetailView(…) and showAddNewBookView().

For now don’t bother about Presenter injection and closing Realm instance. How Presenter and View interfaces look like?

The BooksActivity implements BooksView and implementation of BooksPresenter is shown below.

As you see, Presenter handles the clicks and shows all added books using RealmService. Let’s do a quick look at the BaseActivity and than we go to RealmService.

Injection and close Realm

The BaseActivity is responsible for injecting modules and forcing inheriting Activities to implement closeRealm() method.

Now we open Realm instance in onCreate() and close it in onDestroy() – as it was said in documentation.

BooksModule simply injects BooksPresenter with RealmService to the BooksActivity.

RealmService

As long as we do read queries we are allowed to do them on UI thread and use injected Realm instance field.

The problem occurs with database modifications like write or update. If write operation is not a simple one we should do it on background thread.

We can either use an AsyncTask and in doInBackground() make write operation with new Realm instance between Realm.beginTransaction() and Realm.commitTransaction() or use method Realm.executeTransaction(…).

The first idea is not a good one for our architecture. All database operation should be doing outside the View, so the AsyncTask should be implemented in Presenter or some kind of service, but we also don’t want Android framework in any classes except Views.

Therefore let’s try the second solution.

Method execute() is called in background thread. If there was no exception during operations on database then onSucces() method is called, if not – onError(…). Notice that in execute() body the new instance of Realm is used.

Summary

It is possible to use Realm in MVP architecture. Even if we can’t use Realm instance in different thread than it was created, we can use async transactions mechanizm with callbacks which Realm provides. Opening and closing Realm instance in each Activity and Fragment is not a problem as long as we use Dagger and some base component which views have to inherit.

Do you have any other ideas how to use Realm with MVP? Feel free to comment.