Lessons Learned When Using Realm for Android

Realm is a great alternative to SQLite for data persistence on Android. Today I’m sharing three things to be aware of when using Realm for Android.

No. 1: If you are using a library like Retrofit to return your data model Java objects directly from network calls to your API and then writing those Java objects to the client’s local Realm database, any of the fields that were not included in the server response will be reset to their default values in your local Realm. In other words, let’s say you have an object stored locally in the Realm database, then you query your API to get an update for a part of the object and you receive a partial JSON representation of your object. If you let Retrofit parse that JSON into your Java object data model and then write that object to Realm with a method like copyToRealmOrUpdate, the properties of the local Realm object that were not updated in the JSON will be reset to default.

No. 2: It’s worth noting that to partially update the local Realm objects, your options are rather limited. If your data model Java object has variable names that directly match the names of the properties in the response JSON object, you can hand an Inputstream or JSONObject instance directly to Realm and Realm will only update the properties that are present in the JSON, leaving all other properties the same. Realm does not currently support any way to specify which variable names differ from their corresponding JSON properties (like the SerializedName annotation that Gson offers), so your JSON property names must map directly to your Java object’s property names (the Realm team appears to be addressing the issue https://github.com/realm/realm-java/pull/3758). If such a direct mapping is not possible or convenient, you can manually parse your response JSON and update the fields of the Realm object directly by querying Realm for the object with that id.

No. 3: Unit tests with realm can be tricky to get up and running. The realm-java GitHub repo has an example unit test here (https://github.com/realm/realm-java/tree/master/examples/unitTestExample and more specifically here: https://github.com/realm/realm-java/blob/master/examples/unitTestExample/src/test/java/io/realm/examples/unittesting/ExampleRealmTest.java), but I found that I had to make some minor changes. The unit test uses Robolectric and Powermock in addition to Junit4 and Mockito. The Robolectric version used in the example is outdated so I used 3.3.1, the newest Robolectric version at the time of this blog post. The RobolectricGradleTestRunner is deprecated as of 3.1.1 and should be changed to RobolectricTestRunner. In addition, the sdk can be bumped up to 25, or whatever version you want to target. Here are the annotations I used for my unit test class and the relevant build.gradle dependencies.

Annotations

@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 25, application = TestApplication.class)
@PowerMockIgnore({"org.mockito.*", "android.*", "org.robolectric.*”})
@SuppressStaticInitializationFor("io.realm.internal.Util")
@PrepareForTest({Realm.class})


build.gradle dependencies:

Unit Tests
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.10.19'

More Unit Testing, specifically for Realm

testCompile 'io.reactivex:rxjava:1.2.5'
testCompile "org.robolectric:robolectric:3.3.1"
testCompile 'org.robolectric:shadows-support-v4:3.3.1'
testCompile "org.powermock:powermock-module-junit4:1.6.6"
testCompile "org.powermock:powermock-module-junit4-rule:1.6.6"
testCompile "org.powermock:powermock-api-mockito:1.6.6"
testCompile "org.powermock:powermock-classloading-xstream:1.6.6"