user3806331 user3806331 - 1 year ago 212
Android Question

Android Kotlin Realm Proper Way to Query+Update Async

I recently faced a problem in which i had in memory a RealResult List of objects and was showing it in a view. Upon user click, the current showing item should be marked as deleted in realm (property


So i was just getting that object from the lazy
list, open a transaction and mark it deleted. As the RealmResults are auto-updated, i had a change listener bound to a
. Everything works fine except this warning:

Mixing asynchronous queries with local writes should be avoided. Realm will convert any async queries to synchronous in order to remain consistent. Use asynchronous writes instead

Which is problematic because my list is enormous and i don't want the query to become
. I solved it this way, which i don't know it it is right. Instead of giving the item object to the update function, i give the id of the object, and then do this:

Realm.getDefaultInstance().use { realm ->

realm.executeTransactionAsync {
// find the item
.equalTo(ItemRealm.ID, itemId).findFirstAsync()
.addChangeListener(object : RealmChangeListener<ItemRealm> {
override fun onChange(element: ItemRealm) {
element.deleted = true

The problem which im unsure is the
part of the query inside an async transaction.

Edit. Actually, it throws
java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.

Edit2: Tried this and show Realm access on different thread:

fun setItemDeleted(itemId: Long) {
// write so new realm instance
Realm.getDefaultInstance().use { realm ->
realm.executeTransactionAsync {
// find the item
val item = realm.where(
.equalTo(ItemRealm.TIMESTAMP, itemId).findFirst()
item?.userDeleted = true

Answer Source

Everything in executeTransactionAsync() runs on a background thread, so you should use the synchronous methods to obtain your object inside it.

Realm.getDefaultInstance().use { realm ->
    realm.executeTransactionAsync { bgRealm ->
        // find the item
        val item = bgRealm.where(
                        .equalTo(ItemRealm.ID, itemId).findFirst()
        item?.deleted = true