Really good questions, actually. I’ll do my best to answer it in detail.
It’s fine to have a single instance of the Realm passed around (in fact, I have a counter for my activities, and if that reaches 0 then I close my Realm on the UI thread — I have this in a RealmHolder to change the Realm on the UI thread when it’s closed then re-opened), but from Dagger, you’ll most definitely obtain a Realm that belongs to the UI thread. If you by chance execute any task on a background thread, you’ll need a Realm instance for that given thread.
Closing the UI thread’s Realm is not crucial, because it is on a looper thread with auto-update. The only time that’s an issue is if you intend to use Realm.compactRealm() on non-encrypted Realm, which can be used only if there are no open instances on any threads. If you don’t have background Realms, then you won’t need Realm.compactRealm() in the first place.
However, a Realm opened on a non-autoupdating (non-looper) background thread MUST be closed to prevent issues.
If you don’t use any threads or executors or things like that and you only operate on the UI thread, then you ought to use executeTransactionAsync() so that your writes happen on a background thread, and then use the Realm.Transaction.OnSuccess callback to know when it’s done (or change listeners for the results).
Mixing `executeTransaction()` on the UI thread with `find*Async()` methods is a no-no, because it converts your async queries to sync.
So you have two options —
1.) use only a single UI thread Realm with async methods
2.) separate the writes explicitly to background threads (and there use sync transaction)
But you shouldn’t do sync writes on the UI thread.
Personally I do the writes on a background thread, and listen to changes in the Realm with a change listener on the UI thread, and if something happens, set the data in the views for the current version of the RealmObject/RealmResults.