Live Queries - Android SDK¶
On this page
Objects in Realm clients are live objects that update automatically to reflect data changes, including synced remote changes, and emit notification events that you can subscribe to whenever their underlying data changes. You can use live objects to work with object-oriented data natively without an ORM tool.
Live objects are direct proxies to the underlying stored data, which means that a live object doesn't directly contain data. Instead, a live object always references the most up-to-date data on disk and lazy loads field values when you access them from a collection. This means that a realm can contain many objects but only pays the performance cost for data that the application is actually using.
Valid write operations on a live object automatically persist to the realm and propagate to any other synced clients. You do not need to call an update method, modify the realm, or otherwise "push" updates.
Realm objects accessed on a thread associated with a Looper automatically update periodically to reflect changes to underlying data.
The Android UI thread always contains a
Looper instance. If you need
to keep Realm objects around for long periods of time on
any other thread, you should configure a
Looper for that thread.
Instances of a realm instantiated on a thread that does not have a Looper message loop configured do not automatically advance their version of underlying data. This results in the SDK "pinning" that version of the data, which can cause an increased memory footprint for your instance of Realm Database. Avoid using realm instances on non-Looper threads when possible. When unavoidable, always ensure that you close the realm when you're done using it, or the pinned version will consume application memory indefinitely.
You can read back the data that you have stored in Realm Database. The standard data access pattern across MongoDB Realm SDKs is to find, filter, and sort objects, in that order. To get the best performance from MongoDB Realm as your app grows and your queries become more complex, design your app's data access patterns around a solid understanding of Realm Database read characteristics.
When you design your app's data access patterns around the following three key characteristics of reads in Realm Database, you can be confident you are reading data as efficiently as possible.
Results Are Not Copies¶
Results to a query are not copies of your data: modifying the results of a query will modify the data on disk directly. This memory mapping also means that results are live: that is, they always reflect the current state on disk.
See also: Collections are Live.
Results Are Lazy¶
Realm Database defers execution of a query until you access the results. You can chain several filter and sort operations without requiring extra work to process the intermediate state.
See also: Results are Lazily Evaluated.
References Are Retained¶
One benefit of Realm Database's object model is that Realm Database automatically retains all of an object's relationships as direct references, so you can traverse your graph of relationships directly through the results of a query.
A direct reference, or pointer, allows you to access a related object's properties directly through the reference.
Other databases typically copy objects from database storage into application memory when you need to work with them directly. Because application objects contain direct references, you are left with a choice: copy the object referred to by each direct reference out of the database in case it's needed, or just copy the foreign key for each object and query for the object with that key if it's accessed. If you choose to copy referenced objects into application memory, you can use up a lot of resources for objects that are never accessed, but if you choose to only copy the foreign key, referenced object lookups can cause your application to slow down.
Realm Database bypasses all of this using zero-copy live objects. Realm object accessors point directly into database storage using memory mapping, so there is no distinction between the objects in Realm Database and the results of your query in application memory. Because of this, you can traverse direct references across an entire realm from any query result.
Managed objects are live Realm objects that update based on changes to underlying data in Realm Database. Managed objects can only come from an open realm, and receive updates as long as that realm remains open.
Managed objects cannot be passed between threads.
Unmanaged objects are instances of Realm objects that are not live. You can get an unmanaged object by manually constructing a Realm object yourself, or by calling Realm.copyFromRealm().
Unmanaged objects can be passed between threads.
Any modern app should be able to react when data changes, regardless of where that change originated. When a user adds a new item to a list, you may want to update the UI, show a notification, or log a message. When someone updates that item, you may want to change its visual state or fire off a network request. Finally, when someone deletes the item, you probably want to remove it from the UI. MongoDB Realm's notification system allows you to watch for and react to changes in your data, independent of the writes that caused the changes.
Realm emits three kinds of notifications:
- Realm notifications whenever a specific realm commits a write transaction.
- Collection notifications whenever any Realm object in a collection changes, including inserts, updates, and deletes.
- Object notifications whenever a specific Realm object changes, including updates and deletes.
Subscribe to Changes¶
Generally, this is how you observe a realm, collection, or object:
- Create a notification handler for the realm, collection, or object notification.
- Add the notification handler to the realm, collection, or object that you want to observe.
- Receive a notification token from the call to add the handler. Retain this token as long as you want to observe.
- When you are done observing, invalidate the token.