Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Realm Model Classes

Realm Model Classes

A tale about overcoming the limitations
of the annotation processor

Emanuele Zattin

August 10, 2016
Tweet

More Decks by Emanuele Zattin

Other Decks in Technology

Transcript

  1. REALM MODEL CLASSES A tale about overcoming the limitations of

    the annotation processor Emanuele Zattin - Realm @emanuelez 10-08-2016 - DroidDevs CPH
  2. > Fast, zero-copy, embedded database > Installed on 1 Billion+

    devices > Trusted by tens of thousands of devs > Object & model-oriented > Full ACID transactions > Well defined threading model > Cross-platform C++ core with language bindings
  3. REALM MODEL CLASSES Up to a few months ago Realm

    was imposing several limitations on how model classes were defined They were POJOs, but not quite, so let's see why
  4. Getters had to be called: > get<FieldName>() > is<FieldName>() was

    allowed for boolean fields Setters had to be called: > set<FieldName>()
  5. The Java Annotation Processing API does not allow to introspect

    how methods are implemented. This means that Realm had to "guess" which methods were accessors for which fields.
  6. Wanted to validate user input? public void setName(String name) {

    if (name == null) { // handle the case } this.name = name; }
  7. This was only possible using utility static methods. public static

    boolean isValidName(String name) { return name != null; } public static String getTitledName(Person person) { return "Mr. " + person.getName(); }
  8. Realm generates proxy classes for your model classes. > Person

    ⟶ PersonRealmProxy Because of the reason mentioned before Realm cannot replicate your logic in the proxied accessors. This will of course work fine for standalone objects.
  9. It was not possible to have a method such as

    this one: public String getFullName() { return this.lastName + " " + this.firstName; }
  10. Once again the workaround consisted on static utility methods: public

    static String getFullName(Person person) { return person.getLastName() + " " + person.getFirstName(); }
  11. In theory this could be possible if we stated the

    rule that, in such methods, fields can only be accessed with accessors, but such rule would have been hard to enforce and easy to forget, causing many subtle bugs so we decided to disallow it.
  12. On Realm model classes you could not do this: public

    class Person extends RealmObject implements Parcelable { // ← ☹ // fields and accessors }
  13. Again, this was not possible. public class Person extends RealmObject

    { private String firstName; private int age; // getters & setters public void toString() { return firstName + " is " + age + " years old" } }
  14. Again, we could allow this, but decided not to because

    the misuse would be too easy and provoke subtle bugs
  15. WHAT DOES IT CONSIST OF? Use the Transform API to:

    > add custom accessors to model classes > replace field access with accessors The custom accessors are called: > realmGet$<fieldName> > realmSet$<fieldName>
  16. Accessors with custom names public class Person extends RealmObject {

    private String name; public String thisIsMyNameGetter() { return this.name; } }
  17. Accessors with custom logic public class Person extends RealmObject {

    private String name; public void setName(String name) { if (name == null || name.equals("")) { throw new GreatExceptionOfDoom(); } this.name = name; } }
  18. Custom methods public class Person extends RealmObject { public String

    firstName; public int lastName; public String getFullName() { return this.firstName + " " + this.lastName; } }
  19. Implement interfaces public class Person extends RealmObject implements Parcelable {

    private String name; private int age; // Tedious Parcelable API methods here }
  20. Custom Object methods public class Person extends RealmObject { public

    String name; public int age; public String toString() { return this.name + " is " + this.age + " years old"; } }
  21. !