Realm databases for Android beginners

Using Realm databases in Android apps: A beginner’s tutorial

Android realm database tutorial icon

What is Realm?

Think of a Realm as a database.

A Realm is similar to a database and can contain different kinds of objects. You can use a Realm in your app instead of an SQL database.

The Realm is saved in a file on your device and can be backed up.

You can also create a Realm in memory which is destroyed when you close the realm.

Realm works seamlessly with Android and is very easy to set up and use.

A couple of reasons why you should consider using Realm

  • Very little coding makes Realm easy to set up and easy to use
  • Fast queries taking nanoseconds
  • Safe threading so you can access the same data at the same time from multiple threads
  • Use the same Realm for all your apps, on any major platform
  • Secure your data with transparent encryption and decryption
  • Reactive architecture, meaning you can connect your User Interface to your Realm and data changes will appear automatically, so you will always have the latest data
  • Realm provides utility classes to help you bind your data to list views as well as recycler views
  • Build your local realm database and then connect it to the Realm Mobile Platform to sync your data across all connected devices
  • Add your json objects directly into Realm
  • Over 1 billion users rely on Realm

What do you need to use Realm in your apps?

  • Android Studio >= 1.5.1
  • A recent version of the Android SDK
  • JDK version >=7
  • Realm supports Android from API Level 9 (Android 2.3 Gingerbread) and above

Getting started

It’s easy setting up Realm.

Setting up the dependency and plugin

  • Add the class path dependency to the project level build.gradle file:

realm class path gradle project

Add the class path dependency to the project level build.gradle file

  • Apply the realm-android plugin to the top of the application level build.gradle file

realm plugin gradle module

Apply the realm-android plugin to the top of the application level build.gradle file

Initialise Realm

You would usually initialise Realm in your application subclass’s onCreate():

initialize realm in onCreate()

Initialise Realm in your application

 You’re now ready to use Realm!

Configuring a Realm

You can configure Realm to suite your needs (see the documentation) or simply use the default configuration. We’ll use the default configuration in our tutorial app.

Get your Realm instance

You need to get a realm instance which you keep as long as you need to access your data. Don’t forget to close the Realm when you no longer need to access the data.

We get a Realm instance in our activity’s onCreate() method and close the instance in the activity’s onDestroy() method.

You store Realm Objects in the Realm

Realm Models

Create your object classes and turn them into realm objects by extending the RealmObject class. You then interact with the RealmObject which is a live representation of the data. Modifying this object is immediately reflected wherever a query result is used.

Writing data to the realm

You must wrap any write operation in a write transaction. This ensures that your data will always be in a consistent state as the write transaction is either committed or cancelled.

All changes are written to disk during the commit which will only succeed if all of the changes can be persisted.

Cancelling a transaction discards any changes.

Write transactions block each other so rather use the asynchronous transaction if you are going to be writing data on the UI and in the background at the same time. The asynchronous transaction will run its transaction on a background thread and report back when the transaction is done.

When you commit a write transaction to a Realm, all other instances of that Realm will be notified and automatically updated.

Crash safe

If there is a problem during the transaction and an exception is thrown, the data in the transaction is lost but the Realm is not affected. However if the exception is caught, you should cancel the transaction. This is done automatically if you use exceuteTansaction().

Creating your objects

RealmObjects are strongly tied to a Realm so it is advisable to create them through the Realm. This means that you can then use the newly created RealmObject and it will always reflect the latest data.

Alternatively you can first create the object and then add it later. In this case, if you change the original data object, the change will not be reflected by the returned RealmObject.

Queries: Reading data

Most queries are fast enough to be run on the main thread.

Data is not copied during a Realm read, instead, a reference to the original object is returned.

Queries return a RealmResults object containing a reference to the original object, you then work with the original object.

RealmResults behave similarly to Java’s AbstractList so an empty result returns 0, the size of the list and not null.

Auto-Updating Results

RealmResults contain live data so never have to be re-fetched. Modifying the original objects that affect the query will automatically update the RealmResults object.

Note that because the RealmResults object is auto-updating, you should not rely on counts and indices remaining constant.

Retrieving objects by type

It makes sense to use your RealmObjects type as the basis for your queries. We’ll be using our Contact class type in our tutorial app.

Looping through the results

The RealmResults is iterable so you can loop through it using an iterator or the traditional for loop.

Deletion

You can delete the results of a query from the Realm but you must do so in a write transaction. We’ll show you how later when we discuss the tutorial app.

Asynchronous Queries

You may want to run complex queries on a background thread.

The query immediately returns a RealmResults object which is updated once the query is complete. You can also use a RealmChangeListener which will be called every time the RealmResults are updated to reflect the latest changes in the Realm (usually after a commit).

Our Tutorial using the Realm Mobile Database

What does our tutorial app do?

We demonstrate how to use Realm to save a list of contact details in a Realm. We also show you how to:

  • Query the Realm to get all the contacts
  • Add a new contact to the Realm
  • Delete a single contact in the Realm
  • Update a single contact in the Realm
  • Delete all the contacts in the Realm

Our dummy data

We created a json file containing our dummy contacts data and stored it in our app’s assets folder.

The object of the Realm: Our Contact Model

Our Contact class extends the RealmObject class. We can then create our contact objects within a Realm, using our object class.

Each contact has the following fields:

  • name – a string
  • telephone – an int
  • sex –a string
  • country – a string

You can use a json editor like this one http://www.jsonin.com/jsoneditoronline/ to create your json file.

Our application class: MyApplication

We call Realm.init() in our application class to initialise the Realm library and to create a default configuration that we can use in our activity.

The activity: MyRealmActivity

We have one activity where everything happens.

Laying out our Realm: Our layout

The activity’s layout contains a number of buttons to perform the following:

  • load all the dummy data into the database
  • get and display all the data
  • add a contact to the database
  • delete a contact
  • update a contact
  • show the updated contact’s details
  • delete all the items in the database

The methods handling the button clicks are in the activity.

Getting our Realm

We’ve initialised our Realm in our application class. We now get an instance of our Realm which we’ll use to interact with to save and query data. We do this in our activity’s onCreate() method:

get default instance of Realm in onCreate()

Get an instance of your Realm in the onCreate() method

Closing our Realm

You need to close the Realm instance when you’re finished using it. If you don’t, it could cause memory leaks and unnecessarily increase the size of your Realm file.

We close our Realm in the activity’s onDestroy() method, so it’s open while the activity is alive:

close the realm in onDestroy()

Close your Realm in the onDestroy() method

Entering our Realm: Using the database

We can interact with our Realm once we have initialised and obtained an instance of a Realm.

Loading the dummy data

Our dummy data is stored in a json file in the assets folder. We get the data out of the file and store it in a list, the contactsList.

Pressing the LOAD DATA button saves the list in our Realm:

copyToRealm() to save data in realm

Saving data in our Realm

So what’s happening here?

  • beginTransaction() – starts a transaction . Transactions are used to automatically create, update and delete objects within a Realm. You must wrap all write operations in a write transaction. This ensures that your data is always in a consistent state as the write transaction is either committed or cancelled
  • copyToRealm() - Copies our list of contacts to the Realm, returning a copy of the list. Realm will now only manage this returned copy of the list. Changes to the original list will not be persisted
  • commitTransaction() - All changes since the call to Realm.beginTransaction() are persisted to disk. The Realm now returns to being read-only. All other Realm instances are notified that a change has occurred, and update their objects. Any RealmResults will reflect the changes from this commit

Displaying the dummy data

Pressing the GET ALL DATA button starts a query to find all the contacts in our Realm, displaying the results in the LogCat:

query.FindAll() realm.where() to get data out realm

Querying our Realm

So what’s happening here?

  • RealmQuery – holds the query that we want to perform on our Realm
  • where – we get a typed query (for our Contact class) – we only want to query the Contact objects in our Realm
  • RealmResults – holds a reference to all the matching objects for our query. It will never be null as it reflects a value returned by the size() method
  • findAll() – finds all the objects matching our query condition (the Contact objects)
  • for loop – we iterate through the results and display each contact’s name in the logCat

Adding a single contact

Press the ADD CONTACT button to add a single contact’s details to our Realm.

realm.beginTransaction() realm,createObject() to save data in realm

Add a contact to our Realm

So what’s happening here?

  • beginTransaction() – starts a transaction . Transactions are used to automatically create, update and delete objects within a Realm. You must wrap all write operations in a write transaction. This ensures that your data is always in a consistent state as the write transaction is either committed or cancelled
  • createObject() – creates and adds a new Contact object to our Realm
  • getNewContact() – we get a new contact’s details. Note that we create the object within the transaction. We can now use this object and it will always reflect the latest data
  • commitTransaction() - All changes since the call to Realm.beginTransaction() are persisted to disk. The Realm now returns to being read-only. All other Realm instances are notified that a change has occurred, and update their objects. Any RealmResults will reflect the changes from this commit

Deleting a single contact

Press the DELETE CONTACT button to delete a single contact from our Realm.

realm.executeTransaction() deleteFramRealm() to delete an object in realm

Delete a contact from our Realm

So what’s happening here?

  • RealmQuery – holds the query that we want to perform on our  Realm
  • where – we get a typed query (for our Contact class) – we only want to query the Contact objects in our Realm
  • equalTo() – we want to look for a contact where the name field matches “Jack"
  • findFirst() – finds the first contact that satisfies our query condition
  • if statement – we check whether we have found a contact matching our requirement
  • executeTransaction() – executes the given transaction on our Realm. beginTransaction() and commitTransaction() are called automatically. If an exception is thrown during the transaction then cancelTransaction() will be called instead of commitTransaction()
  • deleteFromRealm() - deletes the object from our Realm
  • Toast – we show a toast if the contact we’re looking for does not exist

Updating a single contact

Press the UPDATE CONTACT button to update a contact’s details.

realm.executeTransaction() execute() to update data in realm

Updating a contact in our Realm

So what’s happening here?

  • RealmQuery – holds the query that we want to perform on our  Realm
  • where – we get a typed query (for our Contact class) – we only want to query the Contact objects in our Realm
  • equalTo() – we want to look for a contact where the name field matches “Peter"
  • findFirst() – finds the first contact that satisfies our query condition
  • if statement – we check whether we have found a contact matching our requirement
  • executeTransaction() – executes the given transaction on our Realm. beginTransaction() and commitTransaction() are called automatically. If an exception is thrown during the transaction then cancelTransaction() will be called instead of commitTransaction()
  • set the name and sex field of the matching contact
  • Toast – we show a toast if the contact we’re looking for does not exist

Show the updated contact

Press the SHOW UPDATED CONTACT DETAILS button to show the updated contact’s details.

realm.where() query.findFirst() to find an object in realm

Query our Realm for a contact

So what’s happening here?

  • RealmQuery – holds the query that we want to perform on our  Realm
  • where – we get a typed query (for our Contact class) – we only want to query the Contact objects in our Realm
  • equalTo() – we want to look for a contact where the name field matches “Petronella"
  • findFirst() – finds the first contact that satisfies our query condition
  • if statement – we check whether we have found a contact matching our requirement
  • we display the matching contact’s details in the LogCat
  • Toast – we show a toast if the contact we’re looking for does not exist

Emptying our Realm: Deleting all the items in the database

We delete all the contacts from our Realm.

realm.executeTransaction() realm.delete() to delete an object in realm

Delete all Contact data in our Realm

So what’s happening here?

  • executeTransaction() – executes the given transaction on our Realm. beginTransaction() and commitTransaction() are called automatically. If an exception is thrown during the transaction then cancelTransaction() will be called instead of commitTransaction()
  • delete() – we delete all the contact objects in our Realm

Here are some useful Realm links

Realm best practices

Realm recipes

Backing up my Realm

Realm sample code

I hope that you have found this tutorial useful, if you did, please consider buying me a cup of coffee to keep me awake!. Thanks.

Other means of saving data in your Android apps

You may also be interested in our Firebase Realtime Database tutorial

We also have a SQLite database tutorial, Using a SQLite database in Android

You can also save primitive data in a SharedPreference file, here’s a tutorial that will show you how: Using Android’s SharedPreferences to save persistent data: a practical example and tutorial

Download the project files here download android tutorials project files