Realm is a mobile database framework for iOS and Android. It is designed as a replacement for SQLITE and Core Data.
I stumbled upon the Realm database while looking for a better database for Collect, our mobile-based data collection tool. It has a complex database structure for saving and retrieving of data. Realm is not an ORM (Object Relation Mapping) based on Sqlite. They built their own persistence engine for speed and simplicity.
Here is what I observed while playing around with Realm.
Getting Started On Realm
- JDK Version >= 7.0
- Android SDK Version >= API 9 (Gingerbread and above)
- Download the release package and unzip.
- Create a new project in Android Studio.
- Copy the realm-Version.jar into app/libs.
- Sync your Android project with Gradle files.
How to Use Proguard
Realm generates the proxy class for each RealmObject at compile time. You can use the configuration below to use Proguard with Realm.
An object can be defined simply by extending to RealmObject. Realm annotations processor will generate proxy classes at the compile time.
Getters and setters will be overridden by the generated proxy classes, so no custom logic added over getters and setters will work.
The primary key can be defined by using @PrimaryKey annotation and field type has to be either int or string or long. Using the primary key makes it possible to use createOrUpdate() method, which updates the object (if one exists) or create a new one.
Realm supports all primitive types: int, long, string, float, double, etc. Moreover, subclasses of RealmObject and RealmList <? extends RealmObject> are supported to model relationships.
RealmList can be used instead of ArrayList, but there is no direct support for Primitive Field Types — string, long, integer, etc. You need to create another object to support ArrayList<String> as mentioned below.
Writing to Realm
All writes operations — adding, modifying and removing objects — must be wrapped inside write transactions. A write transaction can either be cancelled or committed. If a write transaction is cancelled, all changes will be discarded. By using write transactions, your data will always be in a consistent state.
You can simply cancel a transaction if you end up in a situation where you want to discard changes.
Write transactions block each other, so this will result in ANR errors if you are creating a write transaction on both UI and background threads at the same time. To avoid, use the async transaction when writing on UI thread.
Read operations are not blocked, even when write transactions are open.
Querying in Realm
Querying on Realm is way faster than SQLite. Realm query is based on Fluent interface and looks like this:
This gives a new instance of RealmResults where objects are never copied. You just get a reference to the matching objects. The returned RealmResults is never null. It will return you an object with size 0.
All fetches (including queries) are lazy in Realm, and the data object is never copied. For all modifications or deletions of the object in the RealmResults, you must do inside write transactions.
Realm Object deletion is similar to write transaction.
Configuring a Realm
Realm can be configured with RealmConfiguration.Builder. You can define one Realm Configuration in your custom Application class and use it throughout your app by calling Realm.getDefaultInstance();
Using JSON with Realm
JSON can be added directly to Realm through Realm.createObjectFromJson(). Lists of objects are added using Realm.createAllFromJson().
When using Realm with GSON, you need to define an Exclusion strategy.
Serializing Realm Objects to JSON with GSON’s default behaviour as GSON, use field values instead of getters and setters. To make GSON serialization work, we must define a JSONSerializer or a TypeAdapter.
Retrofit is not directly compatible with Realm. Define an external JSON serializer and deserializer to make it work.
- The length of field names has an upper limit of 63 characters.
- Strings and byte arrays (byte) cannot be larger than 16 MB.
- Only private instance fields are allowed for the object.
- Only getter and setter are allowed.
- Realm files can be accessed by multiple threads, but you cannot hand over Realms, Realm objects, queries and results between threads.
- Migration is not properly defined and is in developing stage.
- Realm files cannot be accessed by concurrent processes.
Realm is good to go if you have a simple database structure and querying is complex. Realm is also in beta. Since Realm is backed by a large community, they are pushing updates regularly. It is better to wait for future updates if you’re not in a hurry to get started with Realm.