Sapan Diwakar

Software developer

Follow me on Twitter Check out my code on GitHub View some of my designs on Dribbble Take a look at my Linked In profile

Realm for Android

Realm is a mobile database: a replacement for SQLite & Core Data that works for both iOS and Android. It has a really concise API and works extremely fast. Let's see how we define a model in Realm:

public class User extends RealmObject {  
  @PrimaryKey
  private int identifier;
  private String firstName;
  private String lastName;

  @Ignore
  private int sessionId;

  // Standard getters & setters generated by your IDEā€¦

  // Methods
  public boolean hasLongName() {
    return firstName.length() > 7;
  }

  @Nullable
  public static User currentUser(Realm realm) {
    return realm.where(User.class).findFirst();
  }
}

That's all really good. However, it tends to get really messy as you start adding more fields the objects and their required getters and setters. (as pointed by @zaki50 in comments, Realm now allows public members as well as adding methods to your objects). When using Realm with Kotlin, it becomes really simple again as Kotlin generates all getters and setters for you. Here's the example of the User class in Kotlin

@RealmClass
open class User: RealmObject() {  
  @PrimaryKey
  open var identifier: Int = -1
  open var firstName: String? = null
  open var lastName: String? = null

  @Ignore
  open var sessionId: Int? = null

  // Methods
  public fun hasLongName(): Boolean {
    return firstName.length() > 7
  }

  companion object {
    fun currentUser(realm: Realm?): User? {
      return realm?.where(User::class.java)?.findFirst()
    }
  }
}

What's missing from the Swift equivalent is the support for computed properties. But it is possible to emulate computed properties using ignored transient properties:

@Ignore @Transient private val name: String = ""
fun getFirstName(): String {  
    return "$firstName $lastName"
}

Realm also supports Parceler to bundle your obejcts into Parcelable instances.

// Java
@Parcel(implementations = { UserRealmProxy.class },
        value = Parcel.Serialization.BEAN,
        analyze = { User.class })
public class User extends RealmObject {  
    // ...
}

// Or Kotlin
@Parcel(value = Parcel.Serialization.BEAN, analyze = arrayOf(User::class))
open class User : RealmObject() {  
}

If your model contains RealmList, you need to register a special adapter.

open var files: RealmList<Device>? = null  
  @ParcelPropertyConverter(DeviceListParcelConverter::class) set

class DeviceListParcelConverter : RealmListParcelConverter<Device>() {  
  override fun itemToParcel(input: Device, parcel: android.os.Parcel) {
    parcel.writeParcelable(Parcels.wrap(Device::class.java, input), 0)
  }

  override fun itemFromParcel(parcel: android.os.Parcel): Device {
    return Parcels.unwrap<Device>(parcel.readParcelable<Parcelable>(Device::class.java.classLoader))
  }
}

Using Parceler:

// Convert to Parcel
intent.putExtra(ARG_USER, Parcels.wrap(User::class.java, user))

// Convert back from Parcel
Parcels.unwrap <User> (intent.getParcelableExtra<Parcelable> (ARG_USER))  

That's it for now. I'll be covering some other Realm related things in upcoming posts.