React to Changes - Java SDK
On this page
Register a Realm Change Listener
You can register a notification handler on an entire realm. Realm Database calls the notification handler whenever any write transaction involving that realm is committed. The handler receives no information about the change.
This is useful when you want to know that there has been a change but do not care to know specifically what changed. For example, proof of concept apps often use this notification type and simply refresh the entire UI when anything changes. As the app becomes more sophisticated and performance-sensitive, the app developers shift to more granular notifications.
Suppose you are writing a real-time collaborative app. To give the sense that your app is buzzing with collaborative activity, you want to have an indicator that lights up when any change is made. In that case, a realm notification handler would be a great way to drive the code that controls the indicator. The following code shows how to observe a realm for changes with with addChangeListener():
All threads that contain a Looper
automatically refresh
RealmObject
and RealmResult
instances when new changes are
written to the realm. As a result, it isn't necessary to fetch
those objects again when reacting to a RealmChangeListener
, since
those objects are already updated and ready to be redrawn to the
screen.
Register a Collection Change Listener
You can register a notification handler on a specific collection within a realm. The handler receives a description of changes since the last notification. Specifically, this description consists of three lists of indices:
- The indices of the objects that were deleted.
- The indices of the objects that were inserted.
- The indices of the objects that were modified.
Stop notification delivery by calling the removeChangeListener()
or
removeAllChangeListeners()
methods. Notifications also stop if:
- the object on which the listener is registered gets garbage collected.
- the realm instance closes.
Keep a strong reference to the object you're listening to for as long as you need the notifications.
In collection notification handlers, always apply changes in the following order: deletions, insertions, then modifications. Handling insertions before deletions may result in unexpected behavior.
Realm Database emits an initial notification after retrieving the collection. After that, Realm Database delivers collection notifications asynchronously whenever a write transaction adds, changes, or removes objects in the collection.
Unlike realm notifications, collection notifications contain detailed information about the change. This enables sophisticated and selective reactions to changes. Collection notifications provide all the information needed to manage a list or other view that represents the collection in the UI.
The following code shows how to observe a collection for changes with addChangeListener():
Register an Object Change Listener
You can register a notification handler on a specific object within a realm. Realm Database notifies your handler:
- When the object is deleted.
- When any of the object's properties change.
The handler receives information about what fields changed and whether the object was deleted.
Stop notification delivery by calling the removeChangeListener()
or
removeAllChangeListeners()
methods. Notifications also stop if:
- the object on which the listener is registered gets garbage collected.
- the realm instance closes.
Keep a strong reference of the object you're listening to for as long as you need the notifications.
The following code shows how create a new instance of a class in a realm and observe that instance for changes with addChangeListener():
Unregister a Change Listener
You can unregister a change listener by passing your change listener to Realm.removeChangeListener(). You can unregister all change listeners currently subscribed to changes in a realm or any of its linked objects or collections with Realm.removeAllChangeListeners().
Use Realm in System Apps on Custom ROMs
Realm uses named pipes in order to support notifications and access to the realm file from multiple processes. While this is allowed by default for normal user apps, it is disallowed for system apps.
You can define a system apps by setting
android:sharedUserId="android.uid.system"
in the Android manifest.
When working with a system app, you may see a security violation in
Logcat that looks something like this:
05-24 14:08:08.984 6921 6921 W .realmsystemapp: type=1400 audit(0.0:99): avc: denied { write } for name="realm.testapp.com.realmsystemapp-Bfqpnjj4mUvxWtfMcOXBCA==" dev="vdc" ino=14660 scontext=u:r:system_app:s0 tcontext=u:object_r:apk_data_file:s0 tclass=dir permissive=0 05-24 14:08:08.984 6921 6921 W .realmsystemapp: type=1400 audit(0.0:100): avc: denied { write } for name="realm.testapp.com.realmsystemapp-Bfqpnjj4mUvxWtfMcOXBCA==" dev="vdc" ino=14660 scontext=u:r:system_app:s0 tcontext=u:object_r:apk_data_file:s0 tclass=dir permissive=0
In order to fix this you need to adjust the SELinux security rules in
the ROM. This can be done by using the tool audit2allow
, which ships
as part of AOSP:
Pull the current policy from the device:
adb pull /sys/fs/selinux/policy - Copy the SELinux error inside a text file called input.txt.
Run the
audit2allow
tool:audit2allow -p policy -i input.txt - The tool should output a rule you can add to your existing policy to enable the use of Realm.
An example of such a policy is provided below:
# Allow system_app to create named pipes required by Realm # Credit: https://github.com/mikalackis/platform_vendor_ariel/blob/master_oreo/sepolicy/system_app.te allow system_app fuse:fifo_file create; allow system_app system_app_data_file:fifo_file create; allow system_app system_app_data_file:fifo_file { read write }; allow system_app system_app_data_file:fifo_file open;
audit2allow
is produced when compiling AOSP/ROM and only runs on
Linux. You can read more about it here.
Since Android Oreo, Google changed the way it configures SELinux. The default security policies are now much more modularized. Read more about that here.