I've read the warnings about keeping long-lived Realm
instances on background non-Looper threads. I've also seen the suggestion that opening and closing Realm
instances quickly is not the best idea. Given those constraints (if either is invalid, let me know), I'm trying to identify the best way to use Realm with websockets, where websocket events contain information that requires access to the Realm
.
Particularly, what is the right way to go between these options (or something else entirely?):
Realm
on every eventRealm
at the start of the thread, periodically (every 30s or so) begin and commit transaction on the thread to bring the Realm up to date.Looper
for the thread that handles websocket messages. Create the Realm
instance once on the thread, and leave it open for the thread's lifetime, using the Looper
to keep it up to date.Other things worth noting:
Realm
open on the UI thread. So, as far as I understand, this means the background threads at least do not need to pay the price of schema validation.Open and close the Realm on every event
Personally, I find that to be reliable according to the people who say "their Realm is out of date", so this only makes sense if you actually call refresh() after Realm.getDefaultInstance()
.
Open the Realm at the start of the thread, periodically (every 30s or so) begin and commit transaction on the thread to bring the Realm up to date.
Periodic updates would cause either needless transactions, or be "unaware of change" every now and then.
Also, you actually don't need to commit the transaction to force an update, because beginTransaction()
already brings the Realm to the new version.
realm.beginTransaction();
realm.cancelTransaction();
This would be sufficient on its own for that - but technically, this is a workaround to replace using refresh()
(not part of public API), with also blocking the thread if a transaction is open on another thread.
Allocate a Looper for the thread that handles websocket messages. Create the Realm instance once on the thread, and leave it open for the thread's lifetime, using the Looper to keep it up to date.
If you want to ensure at all times that the current thread is up to date reliably and also without blocking other threads in the process, then this is the way to go.
So the two ways are either:
1.) keep a newSingleThreadedExecutor()
that does queries to the Realm only inside a transaction
2.) keep a HandlerThread
alive for as long as needed, and execute the web socket + query stuff there
(Personally, I've only ever used HandlerThread
with RxJava + AndroidSchedulers.from(handlerThread.getLooper())
).