(Note: This article uses Realm 1.2.0, and realm-android-adapters 1.3.0)

(Latest versions are Realm 4.1.1 and realm-android-adapters 2.1.0)

You might have read my article previously on how to identify typical errors that people make in Realm, and also some info on the overview of how Realm works.

The short version is that Realm allows writes from background threads, which automatically notify the Realm on the UI thread, and the results of the queries you had previously defined get updated. Using change listeners, you can easily adjust your current view state with what’s available in the Realm.

Currently, for RecyclerView , you just have to call adapter.notifyDataSetChanged from a RealmChangeListener added to the RealmResults , all of which RealmRecyclerViewAdapter manages for you automatically.

For a normal view (displaying a detail for example), you would execute your query, check for null , and if it’s available then set your views by the object’s fields (on opening the view and in your RealmChangeListener).

But let’s say you’re somewhat new to Realm.

What do you have to do to make Realm work?

Setting up

First thing first, as specified in the docs, you need to add Realm to your project-level build.gradle.

Then you must apply the plugin in the app level build.gradle.

Once you sync Gradle, Realm will be available to use in your application. I’d also rather add realm-android-adapters already, which contains RealmRecyclerViewAdapter (and RealmBaseAdapter if you’re still using ListView for some unknown reason).

If you’re updating from a VERY old version (pre-0.88.0), you’ll most likely need to clean/rebuild.

Personally, I also tend to add a lengthy Proguard configuration for Realm which I snatched throughout 0.82.2 to 0.89.0. While Realm brings its own Proguard config through the Gradle plugin so this probably isn’t actually needed, I think it’s better to be safe than sorry.

After that, you can actually start coding things! Yay!

Make a model class

First thing first, you should make at least one class that either extends RealmObject, or implements RealmModel and has @RealmClass annotation.

Setting up your UI-thread Realm instance

There are actually two approaches to the UI thread’s Realm. People either make a Realm instance per Activity (or Fragment), and others prefer to make a single Realm instance for the UI thread as a whole.

- Making UI instance per Activity or Fragment

If you intend to make a Realm instance for each Activity/Fragment, you’re meant to open it and close it with the following pattern:

This is the default that’s recommended by the official documentation.

- Making a global Realm instance

This is actually what I tend to do, because I’ve been using a @Singleton component as injector. Don’t forget that both approaches work just as well, and the previous one is a bit simpler.

I set up a retained fragment in my activity which increments the current active Activity count. Open the Realm if the counter went from 0 to 1. Close the Realm if the counter went from 1 to 0.

The setRealmConfiguration() method is so that you can replace the default configuration from instrumentation tests with a config for an inMemory() Realm.

If you use this, then you can easily count activity references using a retained fragment!

Ta-dah, now you can freely access RealmManager.getRealm() anywhere for the UI thread. Or just @Inject this from a module. (Don’t forget that the scoped approach per activity or fragment works too, I just prefer this one because I used @Singleton component over @Subcomponent s).

— — —

The UI thread’s Realm instance is what you would use for queries on the UI thread, such as realm.where(NewsPost.class).findAllAsync() which you’d supply to your RealmRecyclerViewAdapter .

Transactions on the UI thread

You might run into cases when you want to for example edit a post and don’t want to start a background thread for it manually.

This is when realm.executeTransactionAsync() comes into play, which you can use directly from the UI thread, and executes the transaction on a background thread for you.

NOTE: Using synchronous transaction on the UI thread converts all asynchronous queries into synchronous queries. So if you are on the UI thread and you need a transaction, you should use executeTransactionAsync() instead of executeTransaction() , or just start your own thread with an executor.

ANOTHER NOTE: Existing RealmResults instances are updated only on the next looper event (which is when RealmChangeListeners are notified). Changes you make in a synchronous transaction do not immediately reflect on your RealmResults, but only when the listeners are notified. If you’re following this guide, you won’t run into any issue related to this “delayed update”, but it’s worth knowing, I guess.

Setting up Realm instances on background threads

There’s a misconception that “Realm only works on one thread”.

Technically, that’s not true. However, a Realm instance that you open on a given thread only works on that thread. You can’t pass RealmObjects and Realms and RealmResults between threads.

You can open a Realm instance on any thread you want. It’s just worth noting that on background threads, it’s super-crucial important to close your Realm instance at the end of the thread’s execution, always. So use a finally { block for that.

Here’s a longer example of an AsyncTask that uses Retrofit2 to synchronously download some JSON, and then save it to the Realm.

As you can see, all you need to do is open a Realm instance, write into it, and then close it. The views that you set up will automatically update with the new post. Woo!

Wrap up

The key points to remember are the following:

open Realm instance per thread, at the execution of the thread close the Realm instance.

If you use Realm.getDefaultInstance() , there should be a close() pair to it, otherwise your Realm instance will leak, which is very bad on background threads.

, there should be a pair to it, otherwise your Realm instance will leak, which is very bad on background threads. any write into the Realm is notified via a RealmChangeListener bound to a RealmResults , and the RealmResults is kept as a field reference .

bound to a , and . make sure your UI’s updating can run multiple times, thus enabling the RealmChangeListener to update for any change that can occur.

to update for any change that can occur. Use async transactions on the UI thread, and sync transactions on background threads

You might not have noticed, but I never used realm.copyFromRealm() anywhere in the code snippet — don’t forget, Realm is designed to be a zero-copy database, so obviously you shouldn’t have to copy things out :P

anywhere in the code snippet — don’t forget, Realm is designed to be a zero-copy database, so obviously you shouldn’t have to copy things out :P Speaking of which, the id of the RealmObject is sent through the Intent, and not a parcelled copy of the RealmObject. This RealmObject is then queried in the other view. This is because parcelling creates an unmanaged copy, which also doesn’t make sense from a zero-copy perspective.

of the RealmObject is sent through the Intent, and not a parcelled copy of the RealmObject. This RealmObject is then queried in the other view. This is because parcelling creates an unmanaged copy, which also doesn’t make sense from a zero-copy perspective. You might have noticed that I didn’t use RxJava in this example, that’s because I wanted to keep it simple. I do have a repository for that, a bit messy, but it works.

And in case you missed it, I reworked this very outdated tutorial in this repository for the previous article.

— — — — — — — — — — — — — — — — — — — — — — — — — — — -

EDIT: Click here for the follow-up article.