Realm Kotlin 0.4.1 Announcement
Rate this announcement
In this blogpost we are announcing v0.4.1 of the Realm Kotlin Multiplatform SDK. This release contains a significant architectural departure from previous releases of Realm Kotlin as well as other Realm SDK’s, making it much more compatible with modern reactive frameworks like . We believe this change will hugely benefit users in the Kotlin ecosystem.
The Realm Java and Kotlin SDK’s have historically exposed a model of interacting with data we call Live Objects. Its primary design revolves around database objects acting as Live Views into the underlying database.
This was a pretty novel approach when Realm Java was first released 7 years ago. It had excellent performance characteristics and made it possible to avoid a wide range of nasty bugs normally found in concurrent systems.
However, it came with one noticeable drawback: Thread Confinement.
Both of which put a huge burden on developers.
In this mode, you see changes to data as immutable events in a stream, allowing complex mapping and transformations. Consistency is then guaranteed by the semantics of the stream; each operation is carried out in sequence so no two threads operate on the same object at the same time.
In this model, however, it isn’t uncommon for different operations to happen on different threads, breaking the thread-confinement restrictions of Realm.
Looking at the plethora of frameworks that support this model (React JS, RxJava, Java Streams, Apple Combine Framework and Kotlin Flows) It becomes clear that this way of reasoning about concurrency is here to stay.
For that reason we decided to change our API to work much better in this context.
So today we are introducing a new architecture, which we internally have called the Frozen Architecture. It looks similar to the old API, but works in a fundamentally different way.
Realm instances are now thread-safe, meaning that you can use the same instance across the entire application, making it easier to pass around with e.g. dependency injection.
All query results and objects from the database are frozen or immutable by default. They can now be passed freely between threads. This also means that they no longer automatically are kept up to date. Instead you must register change listeners in order to be notified about any change.
All modifications to data must happen by using a special instance of a
MutableRealm, which is only available inside write transactions. Objects inside a write transaction are still live.
Opening a realm now only needs to happen once. It can either be stored in a global variable or made available via dependency injection.
You can now safely keep your realm instance open for the lifetime of the application. You only need to close your realm when interacting with the realm file itself, such as when deleting the file or compacting it.
Since everything is frozen by default, you need to retrieve a live version of the object that you want to update, then write to that live object to update the underlying data in the realm.
Changes to all Realm classes are supported through Flows. Standard change listener API support is coming in a future release.
As all Realm objects are now frozen by default, it is now possible to pass objects between different dispatcher threads without any additional boilerplate:
With the change to frozen architecture, there are some new pitfalls to be aware of:
Unrelated queries are no longer guaranteed to run on the same version.
We will introduce API’s in the future that can guarantee that all operations within a certain scope are guaranteed to run on the same version. Making it easier to combine the results of multiple queries.
Depending on the schema, it is also possible to navigate the entire object graph for a single object. It is only unrelated queries that risk this behaviour.
We will monitor how big an issue this is in practise and will introduce future API’s that can work around this if needed. It is currently possible to detect this happening by setting
Ultimately we believe that these drawbacks are acceptable given the advantages we otherwise get from this architecture, but we’ll keep a close eye on these as the API develops further.
We are really excited about this change as we believe it will fundamentally make it a lot easier to use Realm Kotlin in Android and will also enable you to use Realm in Kotlin Multilplatform projects.