Допустим, мне периодически (каждые 3 секунды) нужно читать список из нескольких RealmObject
с, и я хочу сопоставить эти объекты с простыми объектами данных, которые будут использоваться для заполнения содержимого списков.
Для тех, кто интересуется, есть три причины для этого:
- большая сложность вычисления значений и поведения (видимости, т. Е.) Представлений в
ViewHolder
с в моем случае - Я хочу использовать
ListAdapter
, который должен предоставить DiffUtilCallback
, который будет выполняться в каком-то другом потоке, отличном от пользовательского интерфейса, поэтому выполнение необходимых вычислений в его методах невозможно, поскольку они будут использоваться из потока, в котором они находятсяне создан. - удаление зависимости уровня представления от Realm
Я не могу просто использовать сопрограммы основным способом, которые переходят из одного доступного потока при его выполнении в другой, так как я буду (и я сделал)в конечном итоге получите «Область уже закрыта» * исключение 1018 *.
Единственное решение, которое я придумаю, - это использование диспетчера, использующего только один поток newSingleThreadContext("RealmSingleThreadContext")
, например:
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() }
}
}
Этот класс предоставляется как Singleton через Dagger, и, в конце концов, у меня будет один поток для сопоставления всего приложения в фоновом режиме, и моя «основная» viewModel вызовет в onClosed
метод close()
метод этого класса.
Вот как я его использую:
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) }
}
}
}
Единственное, что функция newSingleThreadContext(name: String)
имеет @ObsoleteCoroutineApi
аннотацию, так что это означает, что она будетудален в ближайшее время.
Мой вопрос: может ли кто-нибудь предложить другое решение, кроме использования этого устаревшего Диспетчера?