Realm Java 3.2: Open Realms Asynchronously, Download Realm, Read-only Flag

We’re releasing version 3.2 of Realm Java today, and with it introducing asynchronously opening a Realm, making read-only Realms as well as more improvements to our synchronized Realm APIs. Read on for all the details on this and more.

Asynchronously opening a Realm

The general recommendation for opening a Realm has always been using Realm realm = Realm.getInstance(configuration). Normally this is extremely fast as we internally cache Realm instances. However, if you have migrations or need to copy an initial file from assets, opening the Realm file for the first time might be a bit slower than you would like.

With 3.2 we now introduce Realm.getInstanceAsync(configuration, callback). This method allows you to open a Realm instance on a background thread and only return once all expensive operations have completed.

One way of using this method can be seen below:

// Let all your activities implement this class
public abstract class BaseActivity extends Activity {
   private Realm realm = null;
   private RealmAsyncTask realmAsyncTask;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       realmAsyncTask = Realm.getDefaultInstanceAsync(new Callback() {
           @Override
           public void onSuccess(Realm realm) {
               if (isDestroyed()) {
                   // If the activity is destroyed, the Realm instance should be closed
                   // immediately to avoid leaks. Or you can call realmAsyncTask.cancel()
                   // in onDestroy() to stop callback delivery.
                   realm.close();
               } else {
                   BaseActivity.this.realm = realm;
                   onRealmReady(realm);
                   // Remove the spinner and start the real UI.
               }
           }
       });
       // Show a spinner before Realm instance returned by the callback.
   }

   @Override
   protected void onDestroy() {
       super.onDestroy();
       if (realm != null) {
           realm.close();
           realm = null;
       } else {
           // Calling cancel() on the thread where getInstanceAsync was called on to
           // stop the callback delivery. Otherwise you need to check if the activity
           // is destroyed to close in the onSuccess() properly.
           realmAsyncTask.cancel();
       }
   }

   // This can be overridden by activities so they can start displaying data once Realm
   // is ready.
   abstract void onRealmReady(Realm realm);
}

Download Realm

Alongside Realm.getInstanceAsync() we also added a new option for synchronized Realms: SyncConfiguration.Builder.waitForInitialRemoteData().

You can enable this option to force Realm to download an initial dataset from the server before reporting the Realm as ready to be opened. This can be beneficial if it doesn’t make sense for your app to display anything until it has a full dataset available. “Full” is determined by the point in time the client contacts the server, so if more data is written by other devices in the meantime, they are not taken into consideration. These changes will of course continue to synchronize in the background after the Realm has been opened.

SyncConfiguration config = new SyncConfiguration.Builder(getUser(), getUrl())
    .waitForInitialRemoteData()
    .build();

// This will not be called until the remote Realm has been fully downloaded.
Realm.getInstanceAsync(new Realm.Callback() {
   @Override
   public void onSuccess(Realm realm) {
       // Use Realm
   }
});

This dataset will only be downloaded the first time the Realm is opened i.e., no local Realm file exists. After that, the Realm will be opened immediately.

Read-only Realms

With 3.2 we also enabled the option to create read-only Realms. These can be useful if you do not want to accidentally write changes to a Realm file.

RealmConfiguration config = new RealmConfiguration.Builder()
       .assetFile("my.realm")
       .modules(new MyModule())
       .readOnly()
       .build();

SyncConfiguration syncConfig = new SyncConfiguration.Builder(getUser(), getUri())
       .waitForInitialRemoteData()
       .modules(new MyModule())
       .readOnly()
       .build();

Marking a Realm as read-only will cause all transactions against that Realm to throw an IllegalStateException.

Note this also prevents writing any schema information to the file, so marking a Realm as read-only only makes sense if you at the same time either set RealmConfiguration.Builder.assetFile() or SyncConfiguration.Builder.waitForInitialRemoteData().

Since the Realm schema is automatically created from all known Realm model classes, there can be an advantage to explicitly enumerate all classes in the provided file. This is done using modules.

Refreshing a Realm

Calling Realm.refresh() will force all asynchronous queries to be synchronous in order to provide a consistent view of the underlying data. You should only use refresh() if you are not using any asynchronous queries.

With the changes introduced to iterators in 3.0, it has now been possible to add Realm.refresh() back after popular demand.

Calling Realm.refresh() will force any Realm instance to the latest version of the database as well as trigger any registered notifications. This has especially been useful if you are using some other notification system than Realm notifications, e.g. event busses.

Other improvements

  • It is now possible for SyncUsers to change their password using the new SyncUser.changePassword(password, callback) API.
  • It is now possible to ask if a given SyncUser is an administrator on the Realm Object Server by calling SyncUser.isAdmin(). Admin users have special capabilities like changing permissions for other users.
  • Transient fields in Realm Model classes will now be treated as implicitly having the @Ignore annotation.
  • DynamicRealmObjects now support reverse relationships as well using DynamicRealmObject.linkingObjects(String parentClass, String parentField).

See the CHANGELOG for the full list of changes.


Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on Stack Overflow, GitHub, or Twitter.