java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.
on realm.copyFromRealm(results) see the code snipper below
because copyFromRealm is expensive and I want to make in the background thread.
Note: I can't obtain a Realm instance on a background thread because the addChangeListener function needs to run on the same thread. Furthermore, the addChangeListener function can't be called on a thread that doesn't have a looper, so I must use the main thread to add the listener. Therefore, I need to find a way to obtain the Realm instance on the main thread, add the listener there, and then perform copyFromRealm on a background thread.
Question: How can I copy results from Realm in a background thread while still listening for changes from the main thread?
Code:
override fun getUsersFlow(projectId: Int?): Flow<List<UserEntity>> {
return callbackFlow {
val realm = Realm.getDefaultInstance()
val projectBasedQuery = realm.where(UserEntity::class.java).apply {
if (projectId != null) equalTo("projectId", projectId)
}
var copyJob: Job? = null
val findAllAsync = projectBasedQuery.findAllAsync()
findAllAsync.addChangeListener { results ->
copyJob = CoroutineScope(Dispatchers.Default).launch {
val items = results.realm.copyFromRealm(results)//CRASH
val sortedItems = items.sortedByDescending { it.createdTime } // Sort updated list by date
trySend(sortedItems)
}
}
awaitClose {
findAllAsync.removeAllChangeListeners()
copyJob?.cancel()
if (!realm.isClosed) {
realm.close()
}
}
}.flowOn(Dispatchers.Main)
}
Solution:
freeze() function is the key. See in the code how it used on
freezedResults.realm.copyFromRealm(freezedResults)Preferable approach:
Refactored: