Я использую LocalDataSource
как единственный источник истины, а RemoteDataSource
используется для его актуализации.
Поскольку emitAll()
и Flow.collect()
блокируются, я сначала получаю последнее кешированное значение , Я загружаю последнее значение из RemoteDataSource
, вставляю их локально и, наконец, я снова начал слушать LocalDatasource
.
Текущее решение:
override fun getById(venueId: String) = flow {
emit(localDataSource.getById(venueId).first())
val remoteVenue = remoteDataSource.getById(venueId)
localDataSource.mergeOrInsert(remoteVenue)
emitAll(localDataSource.getById(venueId).filterNotNull())
}
Можно ли это сделать по-другому , без явного извлечения последнего кешированного значения? Можно ли это сделать, сразу послушав LocalDataSource
и потом вставив скачанное обновление? Основная цель - сделать код максимально ясным. Использование каналов могло бы быть решением, но это, вероятно, отклоняется от цели добавления ясности.
Итак, нерабочий пример A, примерно так:
override fun getById(venueId: String) = flow {
nonBlockingEmitAll(localDataSource.getById(venueId))
val remoteVenue = remoteDataSource.getById(venueId)
localDataSource.mergeOrInsert(remoteVenue)
}
Или рабочий пример B :,
override fun getById(venueId: String) = flow {
CoroutineScope(coroutineContext).launch {
val remoteVenue = wrapCall { remoteDataSource.getById(venueId) }
remoteVenue?.let { localDataSource.mergeOrInsert(it) }
}
emitAll(localDataSource.getById(venueId))
}
В примере B вызов ограничен в рамках потока и не будет протекать, но, возможно, создание CoroutineScope
слишком сложно?
Какой из этих 3 блоков кода лучше ? Есть ли еще лучшее решение?