RealmResults Not Auto-Updating in Kotlin Android App

Hello everyone,

I’m working on an Android app using Kotlin and Realm as my database. One of the issues I’m facing is that my RealmResults list is not auto-updating when the underlying data changes. I expected the list to be “live” and reflect any changes made to the database automatically.

Here’s a simplified version of my code:

object RealmManager {
    var realm: Realm? = null

    @OptIn(DelicateCoroutinesApi::class)
    fun initRealm(context: Context) {
        val config = RealmConfiguration.Builder(
            schema = setOf(TestItem::class, Test2Item::class))
            .name("database")
            .schemaVersion(1) // Set the new schema version to 2
            .migration(AutomaticSchemaMigration {
                /*it.enumerate(className = "Person") { oldObject: DynamicRealmObject, newObject: DynamicMutableRealmObject? ->
                    newObject?.run {
                        // Change property type
                        set(
                            "_id",
                            oldObject.getValue<ObjectId>(fieldName = "_id").toString()
                        )
                        // Merge properties
                        set(
                            "fullName",
                            "${oldObject.getValue<String>(fieldName = "firstName")} ${oldObject.getValue<String>(fieldName = "lastName")}"
                        )
                        // Rename property
                        set(
                            "yearsSinceBirth",
                            oldObject.getValue<String>(fieldName = "age")
                        )
                    }
                }*/
            })
            .build()
        realm = Realm.open(config)
    }

    @JvmStatic
    fun getRealmInstance(): Realm {
        return realm ?: throw IllegalStateException("Realm not initialized. Call initRealm() first.")
    }

    fun getNextId(clazz: KClass<out TypedRealmObject>): Long {
        val maxId: RealmScalarNullableQuery<Long> = realm!!.query(clazz).max("id")
        return maxId.find()?.plus(1) ?: 0 // Falls keine Einträge vorhanden sind, starte bei 0
    }

    @OptIn(DelicateCoroutinesApi::class)
    inline fun <reified T : RealmObject> addItem(item: T) {
        realm?.writeBlocking {
            val nextId = getNextId(T::class)
            if (item is TestItem) {
                item.id = nextId
            } else if (item is Test2Item) {
                item.id = nextId
            }
            try {
                copyToRealm(item)
            } catch (e: Exception) {
                println("error: "+e.message)
            }
        }
    }

    @JvmStatic
    fun getTestItems(fType: Int): RealmResults<TestItem> {
        return realm!!.query<TestItem>("fType == $0", fType).find()
    }


    @JvmStatic
    fun getTest2Items(fType: Int): RealmResults<Test2Item> {
        return realm!!.query<Test2Item>("fType == $0", fType).find()
    }
}

........................................................................

open class TestItem() : RealmObject {
    @PrimaryKey
    var id: Long = 0
    var name: String = ""
    var owner_id: String = ""
    var fType: Int = 0
    constructor(ownerId: String = "") : this() {
        owner_id = ownerId
    }
}
..........................................................
..........................................................

Here is the variable that contains the list:

var testItems: RealmResults<TestItem>? = null
testItems = getTestItems(1)

Here is the Realm version I’m using:

id("io.realm.kotlin") version "1.10.0" apply false

What could be the reason that my list is not updating automatically when a new entry is saved to the Realm database?

Thank you in advance for the help. Regards.

Can’t anyone help me?
I found realm-android much better and easier, but now I’m having problems integrating it into the new Android Studio, so I’m now using realm-kotlin.
I simply can’t make any more progress and will be forced to switch back to SQLite if realm doesn’t work. :frowning:

How do you know the list is not updating? If you’re not watching for changes, the data may change and you would never know it.

I may be a good idea to review the Getting Started Guide React To Changes as that covers how to add an observer to the data so the app is notified of events when the underlying data changes - to which the UI can then be updated to reflect that change.

Maybe you’ve implemented that but omitted it from the question?

Thank you for the message.
I recently did it this way and accordingly updated my list:

val job = CoroutineScope(Dispatchers.Default).launch {
            val testFlow = DataHolder.testItems!!.asFlow()
            val testSubscription = testFlow.collect { changes: ResultsChange<TestItem> ->

                when (changes) {
                    is UpdatedResults -> {
                        if (changes.insertions.isNotEmpty()) {
                            withContext(Dispatchers.Main) {
                                DataHolder.testItems = changes.list
                                adapter!!.updateItems(DataHolder.testItems!!)
                                adapter?.let {
                                    it.notifyItemInserted(DataHolder.testItems!!.size-1)
                                } ?: run {
                                    println("Adapter is null.")
                                }
                            }
                        }
                        if (changes.deletions.isNotEmpty()) {
                            withContext(Dispatchers.Main) {
                                DataHolder.testItems = changes.list
                                adapter!!.updateItems(DataHolder.testItems!!)
                                val deletedIndexes = changes.deletions.sortedDescending()
                                DataHolder.testItems = changes.list
                                for (index in deletedIndexes) {
                                    adapter?.notifyItemRemoved(index)
                                }
                            }
                        }
                    }
                    else -> {
                        // types other than UpdatedResults are not changes -- ignore them
                    }
                }
            }
        }

That already works with adding and deleting the items.
However, I had to reassign the updated list to the adapter so that it always gets updated in the RecyclerView.

Regards