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?