Let's say I periodically (each 3 seconds) need to read a list of some RealmObject
s and I want to map those objects to simple data objects that will be used for filling the content of lists .
For those who wonder, there are three reasons for that:
ViewHolder
s in my caseListAdapter
which needs to have provided DiffUtilCallback
which would be executed on some other thread than UI, so doing needed computations in its methods is not possible, because they would be used from the thread in which they are not created. I can not simply use coroutines in basic way which jump from one available thread in its execution to another, since I will(and I did) eventually receive "Realm is already closed" exception.
The only solution that I come up with is using dispatcher that uses only one thread newSingleThreadContext("RealmSingleThreadContext")
for example:
class RealmSingleThreadContext {
val ctx = NewSingleThreadedContext("RealmSingleThreadContext")
lateinit var realm : Realm
init {
// opening Realm connection for thread "RealmSingleThreadContext"
GlobalScope.launch(ctx) { realm = Realm.getDefaultInstance() }
}
fun close() {
GlobalScope.launch(ctx) { if (!realm.isClosed()) realm.close() }
}
}
This class is provided as Singleton through Dagger and eventually at the end, I will have one thread to do the mapping for whole app in the background and my "main" viewModel, will call in its onClosed
method close()
method of this class.
This is how I use it:
class HomeViewModel @Inject constructor(/* other */var realmSingleThreadContext: RealmSingleThreadContext) {
var topLiveEventsUI: MutableLiveData<List<EventPreviewUI>> = MutableLiveData(listOf())
fun useRealmInBckg() {
viewModeScope.launch(realmSingleThreadContext.ctx) {
topLiveEventsUI.postValue(eventsReadUseCase.getTopLiveEvents()
.map{ mapper.map(it) }
}
}
}
The only thing is that the function newSingleThreadContext(name: String)
has @ObsoleteCoroutineApi
annotation, so it means that it would be removed soon.
My question is: can anyone propose another solution than using this obsoleted Dispatcher?
It's very easy to make your own single-threaded dispatcher from a Java executor:
val singleThreadContext = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With