Since Android was created, we app developers have been using SQLite to store our local data. Sometimes directly with SQL statements, sometimes using an Object-Relational Mapper (ORM) as an abstraction layer, but either way, we’ve been using SQLite at the end of the day.

Despite all of SQLite’s advantages, though, there were times when we wished we had alternatives to a relational model: Something that could spare us from having to add boilerplate code to convert values to and from the database, or enable us to skip setting up mappings between classes and tables, fields and columns, foreign keys, etc.

In other words, a database with data structures more similar to the ones we actually use at the application level. Better yet, if it could be memory efficient by design, allowing for better experiences in resources constrained devices, that would be awesome.

These are, in fact, some of the out-of-the-box benefits we get with Realm, a database platform with a distinct architecture, which has emerged as a new alternative to SQLite.

Realm Is the Best Android Database Solution

This article presents some of the main reasons why Realm has caught so much attention and why you might want to consider trying it. It discusses some of the key advantages that Realm provides to Android developers over SQLite.

Since Realm is available on multiple platforms, some of what will be covered in this article has relevance to other mobile platforms as well, such as iOS, Xamarin, and React Native.

SQLite: It Works, but It is Not What You Need Most of the Time

Most mobile developers are probably familiar with SQLite. It has been around since 2000, and it is arguably the most used relational database engine in the world.

SQLite has a number of benefits we all acknowledge, one of which is its native support on Android.

The fact that it is a standard SQL relational database also minimizes the learning curve for those who come from a relational database background. It also provides reasonably good performance if used to its full potential (leveraging features, such as prepared statements, bulk operations with transactions, etc). Although SQLite may not scale very well for all of your needs.

Dealing directly with SQL statements has a number of downsides, though.

According to the official Android documentation, here are the steps needed to start reading/writing to SQLite:

  1. Describe your schema in terms of contract classes.
  2. Define your create/drop table commands in strings.
  3. Extend SQLiteOpenHelper to run create commands and manage upgrades/downgrades.

Once you’ve done this, you’ll be ready to read and write to your database. However, you will need to convert back and forth between the objects in your application and values in the database. Long story short: It’s a lot of boilerplate code!

Another issue is maintainability. As your project grows larger and the need to write more complex queries arises, you will end up with big chunks of raw SQL queries in strings. If later on you need to change the logic of those queries, it can be quite a hassle.

Despite its downsides, there are cases where using raw SQL is your best option. One example is when you are developing a library where performance and size are critical factors and adding a third-party library should be avoided if possible.

Object-Relational Mapper: The Band-aid For SQL Challenges

To save us from dealing with raw SQL, ORMs came to the rescue.

Some of the most famous Android ORMs are DBFlow, greenDAO, and OrmLite.

The greatest value they bring is SQLite abstraction, letting us map database entities to Java objects relatively easy.

Among other benefits, application developers get to work with objects, a much more familiar data structure. It also helps with maintainability, as we are now handling high-level objects with a stronger typing and leaving the dirty work to the libraries. Less struggling with building queries by concatenating strings or manually handling the connection with the database. Fewer typos.

Although it’s a fact that these ORMs have raised the bar on Android databases, they also have their drawbacks. In many cases, you end up loading unnecessary data.

Here is an example.

Say you have a table with 15 columns, and in a certain screen of your app, a list of objects from this table is displayed. This list displays values from only three columns. Therefore, by loading all data from the table row, you end up bringing five times more data than you actually needed for that screen.

Truth be told, in some of these libraries you can specify which columns you want to retrieve upfront, but for that you need to add further code, and even so, that will not be enough in case you can only know exactly which columns you will use after you look at the data itself: some data might be unnecessarily loaded anyway.

Additionally, there are often scenarios where you have complex queries to make, and your ORM library just doesn’t offer you a way to describe these queries with its API. That can make you write inefficient queries that do more calculation than what you need, for example.

The consequence is a performance loss, leading you to resort to raw SQL. While this is not a deal breaker for many of us, it hurts the main purpose of the object-relational mapping and takes us back to some of the aforementioned issues regarding SQLite.

Realm: A Perfect Alternative

Realm Mobile Database is a database designed for mobile devices from the ground up.

The key difference between Realm and ORMs is that Realm is not an abstraction built on top of SQLite, but a whole new database engine. Rather than a relational model, it is based on an object store. Its core consists of a self-contained C++ library. It currently supports Android, iOS(Objective-C and Swift), Xamarin, and React Native.

Realm was launched in June 2014, so it is currently two and a half years old (pretty new!).

While server database technologies were going through a revolution since 2007, with many new ones emerging, the database technology for mobile devices remained stuck with SQLite and its wrappers. This was one of the key motivations to create something from scratch. Furthermore, as we will see, some of Realm’s features required fundamental changes to the way a database behaves at a low level, and that was just not possible building something on top of SQLite.

But is Realm really worth it? Here are the top reasons why you should consider adding Realm to your tool belt.

Easy modeling

Here’s an example of some models created with Realm:

public class Contact extends RealmObject {
    @PrimaryKey
    String id;
    protected String name;
    String email;
    @Ignore
    public int sessionId;

    //Relationships
    private Address address;
    private RealmList<Contact> friends;

    //getters & setter left out for brevity
}
public class Address extends RealmObject {
    @PrimaryKey
    public Long id;

    public String name;
    public String address;
    public String city;
    public String state;
    public long phone;
}

Your models extend from RealmObject. Realm accepts all primitive types and its boxed types (except for char), String, Date and byte[]. It also supports subclasses of RealmObject and RealmList<? extends RealmObject> to model relationships.

Fields can have any access level (private, public, protected, etc). All fields are persisted by default, and you just need to annotate “special” fields (e.g., @PrimaryKey for your primary key field, @Ignore to set non-persisted fields, etc.).

The interesting thing about this approach is that it keeps classes less “annotation polluted” in comparison to ORMs, as in most of them you need annotations to map classes to tables, regular fields to database columns, foreign key fields to other tables, and so on.

Relationships

When it comes to relationships, there are two options:

  • Add a model as the field from another model. In our example, the Contact class contains an Address field and that defines their relationship. A contact might have an address, but nothing stops this same address from being added to other contacts. That allows for one-to-one and one-to-many-relationships.

  • Add a RealmList of the models being referenced. RealmLists behave quite like good old Java Lists, acting as a container of Realm objects. We can see that our Contact model has a RealmList of contacts, which are her friends in this example. One-to-many and many-to-many relationships can be modeled with this approach.

I like this way of representing relationships because it feels very natural to us Java developers. By adding these objects (or lists of these objects) directly as fields of our class, just like we would do for other non-model classes, we don’t need to deal with SQLite settings for foreign keys.

Caveat: There is no support for model inheritance. The current workaround is to use composition. So if, for example, you have an Animal model and were hoping to create a Dog model extending from Animal, you will instead have to add an Animal instance as a field in Dog. There is a big debate on Composition vs. Inheritance. If you are into using inheritance, this is definitely something you need to know about Realm. With SQLite, this could be implemented using two tables (one for the parent and one for the child) connected by a foreign key. Some ORMs also don’t impose this restriction, like DBFlow.

Retrieve Only Data You Need! Zero-copy Design

This is a killer feature.

Realm applies the concept of zero-copy design, which means that data is never copied to memory. The results you get from a query are actually just pointers to the real data. The data itself is lazily loaded as you access it.

For example, you have a model with 10 fields (columns in SQL). If you query for objects of this model to display them listed on a screen, and you just need three out of the 10 fields to fill the list items, those will be the only fields retrieved.

As a consequence, queries are blazingly fast (see here and here for some benchmark results).

This is a big advantage over ORMs which usually load all data from selected SQL rows upfront.

Screen loading becomes vastly more efficient as a result without requiring any further effort from the developer: it’s just Realm’s default behavior.

Additionally, this also means that apps consume less memory and, considering we’re talking about a resource-constrained environment such as mobile devices, that can make a big difference.

Another consequence of the zero-copy approach is that objects managed by Realm are auto-updated.

Data is never copied to memory. If you have results from a query, and another thread has updated this data on the database after your query, the results you possess will already reflect these changes. Your results are only pointers to the actual data. So when you access values from fields, the most up-to-date data is returned.

If you have already read data from Realm objects and displayed them on the screen, for example, and want to receive updates for when the underlying data changes, you can add a listener:

final RealmResults<Contact> johns = realm.where(Contact.class).beginsWith("name", "John ").findAll();
johns.addChangeListener(new RealmChangeListener<RealmResults<Contact>>() {
      @Override
      public void onChange(RealmResults<Contact> results) {
          // UPDATE UI
      }
});

It’s Not Just a Wrapper

Although we have dozens of options for ORMs, they are wrappers, and it all comes down to SQLite underneath, which limits how far they can get. In contrast, Realm is not just another SQLite wrapper. It has the freedom to provide features that ORMs just can’t offer.

One of the fundamental changes with Realm is being able to store data as an object graph store.

This means Realm is objects all the way down, from the programming language level to the database. Consequently, there’s way less conversion being made back and forth as you write and read values, in comparison to a relational database.

Database structures reflect more closely data structures that application developers use. In fact, this is one of the major reasons why there’s a movement away from relational modeling and toward aggregate models on server-side development. Realm finally brings some of these ideas to the mobile development world.

If we think of components in Realm’s architecture, at the bottom there is its core with the most fundamental implementation of the platform. On top of it, we will have binding libraries to each supported platform.

When using a wrapper for some technology you have no control over, you eventually need to provide some sort of abstraction layer around it.

Realm binding libs are designed to be as thin as possible, to cut out abstraction complexity. They mostly propagate the design idea from Core. By having control of the whole architecture, these components work in better sync with each other.

One practical example is the access to other referenced objects (foreign keys in SQL). Realm’s file structure is based on native links, so when you query for relationships, rather than having to translate an ORM abstraction to relational and/or join multiple tables, you get raw links to the objects at a file system level in the file format.

That’s objects pointing directly to other objects. Thus, querying a relationship is the same as querying an integer column, for example. No need for expensive operations traversing foreign keys. It’s all about following pointers.

Community & Support

Realm is under active development and has been releasing updated versions pretty often.

All components from the Realm Mobile Database are open-source. They are very responsive on their issue tracker and Stack Overflow, so you can expect good and fast support on these channels.

Also, feedback from the community is taken into account when prioritizing issues (bugs, improvements, feature requests, etc.). It’s always good to know you can have a say in the development of the tools you use.

I started using Realm in 2015, and since then, I’ve bumped into several posts on the web with various opinions about Realm. We will talk about its limitations soon, but one thing I’ve noticed is that many of the complaints made at the time of the post have since been fixed.

When I got to know about Realm, for example, there was no support yet for custom methods on models and asynchronous calls. These were deal breakers for many at the time, but both are currently supported.

Such development speed and responsiveness makes us more confident that we won’t be waiting long for important features.

Limitations

As with everything in life, Realm is not all roses. Besides the inheritance limitation previously mentioned, there are other shortcomings to bear in mind:

  • Although it’s possible to have multiple threads reading from and writing to the database at the same time, Realm objects cannot be moved across threads. So if, for example, you retrieve a realm object using AsyncTask’s doInBackground(), which runs in a background thread, you cannot pass this instance to the onPostExecute() methods, since those run on the main thread. Possible workarounds for this situation would be to either make a copy of the object and pass it along or pass the object’s id and retrieve the object again on onPostExecute(). Realm offers synchronous and asynchronous methods for read/write.

  • There’s no support for auto-increment primary keys, so you will need to handle the generation of these yourself.

  • It’s not possible to access the database from distinct processes at the same time. According to their documentation, multi-process support is coming soon.

Realm Is The Future of Mobile Database Solutions

SQLite is a solid, robust, and proven database engine, and relational databases are not going away anytime soon. There are a number of good ORMs out there what will do the trick for many scenarios as well.

However, it is important to keep up-to-date on current trends.

In this regard, I think that Realm is one of the biggest upcoming trends in recent years when it comes to mobile database development.

Realm brings with it a unique approach to deal with data that’s valuable to developers, not only because it can be a better option than existing solutions, but also because it broadens our horizons in terms of new possibilities and raises the bar on mobile database technology.

Do you already have experience with Realm? Please feel free to share your thoughts.

About the author

Mateus Gondim Romão Batista, Brazil
member since November 27, 2014
Mateus is an experienced Java developer who has been focusing on Android for the last two and a half years. He has also developed web projects using Python, Django, and JavaScript. Mateus is a thoughtful, calm person who doesn't rush with solutions, but takes the time to think the problem through in order to solve it properly. He is also excellent at communicating and can clearly explain his ideas and code. [click to continue...]
Hiring? Meet the Top 10 Freelance Android Developers for Hire in December 2017

Comments

Vadim
Thank you Mateus. I have no expereince in mobile development and it was very interesting to know about new DB. > Database structures reflect more closely data structures that application developers use. It is not always good. For example when you work with legacy code or share data model between several apps, then your data model is different from app(s) model perforce. In this case relation DB gives you necessary level of abstraction.
Basanth Verma
Well said!
AbdulHakim Khalib Haliru
apt and beuatifully short. It was a great read. I look forward to trying our Realm.
Abdullah Al Hasan
A good reed! (Y)
Vivek Solanki
Thank you ^_^
Phantom
I already used Realm but 2015 it has much problems with threading. It's also not good that you have to extend RealmObject. In some rare cases you have a domain object where you need to extend it from a special class. In this case you can't use realm very well.
Tiep Doan
I've been using Realm.io for 1 year and my experiences were really painful. With Realm you cannot pass objects cross threads, maintaining live Realm objects is dangerous and prone to crash, Realm has no support for cascading deletion of nested objects, also you must always use executeTransaction() to get the latest version of the database, no LIMIT support in query...etc. For data notifying mechanism, I suggest using SQLBrite which can achieve the same functionality. In short, not worth to use in production and in a team.
Christian Melchior
You are not required to extend `RealmObject` anymore, you can just implement the `RealmModel` interface instead: https://realm.io/docs/java/latest/#realmmodel-interface
Christian Melchior
I'm sorry to hear you had problems with Realm, we do try to be as intuitive to use as possible, but clearly we failed in your case. A few comments though: - Thread-confined objects are very much by design, and they eliminate a whole host of problems you normally see with multi-threaded code. You can read more about it here: https://realm.io/news/threading-deep-dive/ - If you use the recommended approach for controlling the Realm instance lifecycle you really shouldn't see issues with the live objects: https://realm.io/docs/java/latest/#controlling-the-lifecycle-of-realm-instances and https://realm.io/docs/java/latest/#closing-realm-instances - We have cascading delete on the roadmap, but it is possible to implement similar logic yourself: https://github.com/realm/realm-java/issues/1104 - LIMIT is being tracked here: https://github.com/realm/realm-java/issues/544, but note that due to Realms lazy-loading architecture, it is a lot less needed than what you think - Having all writes inside transactions is very much by design as well, and guarantee the ACID properties you normally really want in a database. SQLite behave the same way.
Ali D'ace
I've used Realm for one project and it will never use again. It's fast to develop using realm but it's harder to track the crash and object invalidation, really it's "pain in the ass" :(
Mrunal Khatri
As we have sql, rdbms, adodb and many other database for the web development. Just like the web we have android as a separate platform so many database of it is going to be there and all will have different solutions for sure..
Jean Nkuru
Until the Realm can allow us to use Realm Objects on 2 different threads, many developers (including me) will never endorse Realm-Java as the best android DB solution. It's a critical function. I worked on a chat app similar to whatsapp where messages are stored locally and I have to say the experience from users was quite painful and I had to replace it quickly.
fariha ashraf
one day it will sure be considered as the perfect good db in future :) good luck
comments powered by Disqus
Subscribe
The #1 Blog for Engineers
Get the latest content first.
No spam. Just great engineering posts.
The #1 Blog for Engineers
Get the latest content first.
Thank you for subscribing!
Check your inbox to confirm subscription. You'll start receiving posts after you confirm.
Trending articles
Relevant Technologies
About the author
Mateus Gondim Romão Batista
Java Developer
Mateus is an experienced Java developer who has been focusing on Android for the last two and a half years. He has also developed web projects using Python, Django, and JavaScript. Mateus is a thoughtful, calm person who doesn't rush with solutions, but takes the time to think the problem through in order to solve it properly. He is also excellent at communicating and can clearly explain his ideas and code.