Search code examples
androidrealm

How to transfer RealmResults accross threads


I'm using a recycler view in my app and would like to do some computation on a background thread, obtain a list of RealmObjects, and refresh my adapter to it.

As a bit of background, I have a non trivial sorting requirement, and the recycler view needs to display objects that result from queries on different tables(though they still produce the same object type). I don't want to do these potentially expensive queries on the main thread.

What is the best way to do this? AFAIK, I can

  1. Get a list of ids(String) from the background thread, and do a query on the main thread. So I would do something like realm.where(ObjectA.class).in(listOfIds).findAll(). However, I don't think I have a guarantee that the order of the collection is the order of my listOfIds, which i have sorted in the background. I could then sort the realm collection manually.

  2. Or, I can do a realm.copyFromRealm(listOfObjectA), assuming I have gotten a list of objects from my background thread. With this way it feels cleaner to me but i obviously lose the auto-refreshing functionality, not to mention that it will be memory-intensive. It seems that the expensive copying would take place on the main thread, which would undermine my efforts to move things into the background thread.

I was hoping there was a method that would allow me to transfer RealmResults or RealmList from one thread to the other. Does anyone have recommendations on how to do this?


Solution

  • findAllSortedAsync

    I have a non trivial sorting requirement

    If this sorting is based purely on your RealmObject fields, you can use RealmQuery.findAllSortedAsync(...) method, which will execute the query and sorting for you on a separate worker thread. This is the best option. If it's possible, you can also do sorting in two stages, one using findAllSortedAsync and second one on main thread on already obtained objects - possibly the second stage would not be as costly if the results are pre-sorted by realm.

    and the recycler view needs to display objects that result from queries on different tables

    You can look for a possibility to create a linking between these objects, for example if RealmObject A has a field b, you can sort A by fields of b also - this could fix your problem, and keep everything in one realm query.

    Requery with sorted IDs (NO)

    Get a list of ids(String) from the background thread, and do a query on the main thread...

    You're right - there is no guarantee of the results being returned in the original ID list order, so this is not really an option.

    copyFromRealm

    Or, I can do a realm.copyFromRealm(listOfObjectA)...

    That is correct, however you have to be aware of the limitiations and memory overhead using this method, namely:

    • you get a snapshot of the data and have to manually update the recycler with new snapshots
    • single change to an object conforming to your original query will trigger an update and, possibly, sorting all over again

    It seems that the expensive copying would take place on the main thread, which would undermine my efforts to move things into the background thread.

    Not really, if you perform copyFromRealm on thread A and pass the list to thread B, the hard copying of the values from realm will be executed by thread A, so it's fine.