EDIT: Any Realm version from 4.0.0-RC1 and above supports
RealmList<String> natively, so use that instead.
— — — — — — — — — — — — — — — — — — — —
I’ll be honest: I really dislike titles that say, “X is an anti-pattern”. Especially when the pitfalls of a specific approach aren’t obvious, the opposite is also claimed to be an anti-pattern, and so on.
In the case of
RealmList<RealmString>, you can’t really “support” it at all. I even should have mentioned this already in my Realm schema design article. The idea of using
RealmList<RealmString> to overcome the limitation that
RealmList of primitives is not supported (WHICH IS NOT A LIMITATION SINCE 4.0.0) was designed as a hack, back when there was no better solution. Apart from being hideous and not exactly transient to the developer, it also brings some problems along with it.
Well, there is a just as hacky solution, but at least you don’t bloat your Realm schema with it :)
You need to create a RealmObject for something that isn’t really meant to be a separate class, an unnecessary wrapper. It also creates a link, which means…
Basically if you use
RealmList<RealmString> in a class, then in order to clear up the
RealmString objects bound to it, you must iterate the RealmResults first, call
deleteAllFromRealm() on their managed RealmList, and only then can you actually delete the objects. Iterating a RealmResults creates a proxy per accessed object, so this can be memory-intensive with large datasets, even though this data should belong directly to the RealmObject, not via a link.
Simply put, a link query takes more time than a query on an indexed field.
RealmStringtable notifies any other
RealmObjectthat has a
link to it (pre-3.0)
(only applies before Realm 3.0) The coarse-grained change listeners assume that your object could have been modified if
RealmString was modified, which results in unnecessary calls to
RealmChangeListener, which typically calls
Yup, the problem is that people try to store the primitives as a
List. It doesn’t have to be a List, though. Think about it — you can parcel any List of elements into a String. Even your every-day JSON parser does it all the time.
Parcelling a list to a String is especially easy with a list of primitive values.
Instead of creating an unnecessary wrapper for the
List<String>, instead it maps it into a single
String field, with join separators. For Java, this can be done with Commons-Lang’s
StringUtils.join(), or Stream API backports. Or manually with
StringBuilder. Whichever works.
Since Realm 0.88.0, you need to add Realm to the project as a Gradle plugin, right? Well with that came in the Realm-Transformer, which converts all direct field access into proxy method calls.
This is great, because this is what allows us to manually create “computed properties” like
this.total = quantity * price;.
But this allows us to create custom getters/setters, that set the String field even though you give it a List, or returns a List even though the field is a String.
Something like this:
And if we don’t want to add
Commons-Lang to the project, you can use this method from Spring Framework:
Or something of that sort. Joining a string shouldn’t be too hard.
Don’t create unnecessary links. Purge the
But if you still need to separate the elements into their own list, then create a separate RealmObject for it, not a
RealmString. Here is a concrete example:
This way, you retain a bidirectional link, your TelephoneNumber is independently queryable and sortable, allows queries such as
find the telephone numbers that contains “___", and then use
telephoneNumber.getPerson() to get whom it belongs to.