Realm object not up to date

114 views Asked by At

I have a singleton TimeManager that permanently listens to changes in my Session to perform backoffice stuff.

In the code below, I'm adding a TimeInterval object to the timeIntervals RealmList of my Session object after deleting the existing ones, each time a Session changes.

On a first change triggered by the UI, everything is fine and my Session has one TimeIntervalobject.

On a second change triggered by the UI, what's going wrong is that nothing is deleted when I do session.timeIntervals.deleteAllFromRealm() as session.timeIntervals is empty, as the Timber log shows.

So it looks like the timeIntervals RealmList is not up to date, but calling realm.refresh() does not solve the issue. If I restart my app between the two changes, everything is fine.

I've tried to add an onSuccess listener just to see if it was called and it does. There is pretty much no lag as I'm doing this on an empty Realm.

Here is the code:

object TimeManager {

    var sessions: RealmResults<Session>? = null

    private val sessionIdsToProcess = mutableSetOf<String>()
    
    fun configure() {} // launch init

    fun sessionChanged(session: Session) {
        this.sessionIdsToProcess.add(session.id)
    }

    init {

        val realm = Realm.getDefaultInstance()

        sessions = realm.where(Session::class.java).findAllAsync()
        sessions?.addChangeListener { _, _ ->

            if (sessionIdsToProcess.isNotEmpty()) {

                realm.executeTransactionAsync({ asyncRealm ->

                Timber.d("in asyncRealm {")

                val sessions = sessionIdsToProcess.mapNotNull { asyncRealm.findById(Session::class.java, it) }
                sessionIdsToProcess.clear()

                for (session in sessions) {
                    Timber.d("   Session id = ${session.id}")
                    Timber.d("   Session time intervals count = ${session.timeIntervals.size}")
                    session.timeIntervals.deleteAllFromRealm()
                    val fti = TimeInterval()
                    session.timeIntervals.add(fti)
                    asyncRealm.insertOrUpdate(session)
                }
                Timber.d("}")

                }, {
                    Timber.d("executeTransactionAsync onSuccess listener...")
                    val timeIntervals = realm.where(TimeInterval::class.java).findAll()
                    Timber.d("Total timeIntervals count = ${timeIntervals.size}")

                    timeIntervals.forEach {
                        Timber.d(">>> Time interval session count = ${it.sessions?.size}, session id = ${it.sessions?.firstOrNull()?.id}")
                    }

                }, {})
            }
        }
    }
}


class MainActivity : AppCompatActivity() {

    [...]

    // action triggered by a button
    private fun updateSession() {
    
        Timber.d("Update session")
    
        session.size = Random.nextInt()
        TimeManager.sessionChanged(session)
    
        realm.executeTransactionAsync {
            it.insertOrUpdate(this.session)
        }
    
    }

}

open class Session : RealmObject() {

    @PrimaryKey
    var id = UUID.randomUUID().toString()

    var size: Int? = null

    var timeIntervals: RealmList<TimeInterval> = RealmList()

}

open class TimeInterval : RealmObject() {

    @PrimaryKey
    var id = UUID.randomUUID().toString()

    @LinkingObjects("timeIntervals")
    val sessions: RealmResults<Session>? = null

}

Here are the Timber logs:

First change:

D/MainActivity: Update session
D/TimeManager: in asyncRealm {
D/TimeManager: Session id = 0e6e4eab-61a6-4848-bcb4-ce805b41de16
D/TimeManager: Session time intervals count = 0
D/TimeManager: }
D/TimeManager: executeTransactionAsync onSuccess listener...
D/TimeManager: Total timeIntervals count = 1
D/TimeManager: >>> Time interval session count = 1, session id = 0e6e4eab-61a6-4848-bcb4-ce805b41de16

Second change:

D/MainActivity: Update session
D/TimeManager: in asyncRealm {
D/TimeManager: Session id = 0e6e4eab-61a6-4848-bcb4-ce805b41de16
D/TimeManager: Session time intervals count = 0
D/TimeManager: }
D/TimeManager: executeTransactionAsync onSuccess listener...
D/TimeManager: Total timeIntervals count = 2
D/TimeManager: >>> Time interval session count = 0, session id = null
D/TimeManager: >>> Time interval session count = 1, session id = 0e6e4eab-61a6-4848-bcb4-ce805b41de16

Now if I stop my app after the first change and launch it again, here are the logs I get for the second change (the id changes because I started from scratch):

TimeManager: Session id = 534e9294-6462-4efa-aaf9-834d085aa2ba TimeManager: Session time intervals count = 1
TimeManager: executeTransactionAsync onSuccess listener...
TimeManager: Total timeIntervals count = 1
TimeManager: >>> Time interval session count = 1, session id = 534e9294-6462-4efa-aaf9-834d085aa2ba

How to make sure that session.timeIntervals is up to date?

0

There are 0 answers