3

Is it ok to write to Realm on the main thread?

Basically I'd like to write some ObjectA to Realm right before starting ActivityA.

Once ActivityA starts it needs immediate access (in onCreate) to ObjectA - can I also read on the main thread?

Basically this ObjectA is too large to pass through the bundle so I need to store it in a cache.

I was initially thinking of storing the object in an in-mem cache and then storing it in Realm after the activity starts, but was wondering if I could skip having to write my own in-mem cache.

b.lyte
  • 6,518
  • 4
  • 40
  • 51
  • How do you obtain `ObjectA`? Can you put it in Realm via `initialData()`? The reason why it's generally not recommended to use transaction on the UI thread is because 1.) background thread transactions block `beginTransaction()` call, so you can ANR out if you have bg thread transactions and 2.) it forces async queries to be executed synchronously. Otherwise it works and you'll want to use `findFirst()` anyways – EpicPandaForce Jun 09 '17 at 16:45
  • What's `initialData()`? Yeah it makes sense that we want to run these on the background thread. Hence why I'm thinking of first storing this data in memory and then lazily storing it in Realm. Was just wondering if I could avoid the in mem cache with Realm, but looks like I can't. – b.lyte Jun 09 '17 at 16:59
  • Why not show a spinner, store in a background thread, wait until it’s done, hide spinner, start activity, read on main thread in activityB (reading is fast if it’s a single object), you pass it the ID of the object. – Martin Marconcini Jun 09 '17 at 17:03
  • @clu hm? I just said that you **can** avoid the in-mem cache with Realm – EpicPandaForce Jun 09 '17 at 17:07
  • Really? I guess I didn't understand your comment. If I want to avoid storing the object on the main thread than I have to do it in the background thread. In which case I need to also load it from the background thread. Which is fine, but I'd have to show a spinner (as Martin suggests) while it loads from the bg thread. Is that what you meant? If not, can you please elaborate. Thanks! – b.lyte Jun 09 '17 at 17:17
  • `In which case I **need to also load it from the background thread**.` wrong, because that's not how Realm works. Realm provides lazy-loaded thread-confined proxy, for UI thread you need to access the object on UI thread with a UI thread Realm instance. In your case, if you don't have long-running background thread transactions, even saving on UI thread is fine. – EpicPandaForce Jun 09 '17 at 18:53

2 Answers2

3

Is it ok to write to Realm on the main thread?

Writing to Realm on the UI thread has two implications:

1.) any RealmResults created by asynchronous query api will be evaluated immediately and synchronously on UI thread when the transaction is opened

2.) if a background thread is already writing to Realm in a transaction, then it will block UI thread until that transaction is committed.

In your use-case, you seem to rely on Realm for immediate caching on the UI thread for a single object, so you can write (without getting blocked), and you need the single object immediately (so you need findFirst() which is synchronous API).

So in your case it's most likely safe to use Realm on UI thread.


In general, the Realm best practice is to write to Realm on background thread, and read from Realm on UI thread (by keeping field reference to RealmResults, adding a RealmChangeListener to it, and then receiving the updated results on each change made to Realm).

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
  • Awesome! Thanks for the answer :). Also do you know where this is documented on realm.io? If you don't have it off hand don't worry about it. – b.lyte Jun 10 '17 at 01:55
  • Wow I never replied, wtf, anyways see here https://medium.com/@Zhuinden/https-realm-io-docs-java-latest-writes-says-da18d732f007 – EpicPandaForce Jul 31 '18 at 21:33
0

In general it's bad practice to do anything other than UI on main thread.

We have an app doing as explained in other answers (writing on background thread, reading on UI thread) and it's causing lots of ANRs. On high-end devices it's nearly not noticeable, however on low end devices it takes frequent ANRs (in seconds) constantly.

For that reason, we are removing any DB loading we have in onCreate and recommend anyone doing so as well.

It's best to have the UI shows a loading message/icon than have the whole activity dead for several seconds.