Моя архитектура выглядит следующим образом:
Методы Дао, возвращающие Flow<T>
:
@Query("SELECT * FROM table WHERE id = :id")
fun itemById(id: Int): Flow<Item>
Уровень репозитория, возвращающий элементы из БДно также обратная засыпка из сети:
(* Нужна помощь здесь - это не работает, как задумано **)
fun items(): Flow<Item> = flow {
// Immediately emit values from DB
emitAll(itemDao.itemById(1))
// Backfill DB via network request without blocking coroutine
itemApi.makeRequest()
.also { insert(it) }
}
Слой ViewModel принимает поток, применяялюбые преобразования и преобразование их в LiveData с использованием .asLiveData ():
fun observeItem(): LiveData<Item> = itemRepository.getItemFlow()
.map { // apply transformation to view model }
.asLiveData()
Фрагмент, наблюдающий выбросы LiveData и обновляемый пользовательский интерфейс:
viewModel.item().observeNotNull(viewLifecycleOwner) {
renderUI(it)
}
Проблема, с которой я столкнулся, заключается в шаге 2. Кажется, я не могу найти способ структурировать логику так, чтобы я мог немедленно генерировать элементы из Flow, а также выполнять выборку по сети без ожидания.
Поскольку выборка из сетевой логики находится в той же функции приостановки, он будет ждать завершения сетевого запроса, прежде чем отправлять результаты в нисходящем направлении. Но я просто хочу запустить этот запрос независимо, поскольку мне не интересно ждать результата (когда он вернется, он обновит Room, и я получу результаты естественным образом).
Есть мысли?
РЕДАКТИРОВАТЬ
Решение Марко хорошо работает для меня, но я попробовал подобный подход, например так:
suspend fun items(): Flow<List<Cryptocurrency>> = coroutineScope {
launch {
itemApi.makeRequest().also { insert(it) }
}
itemDao.itemById(1)
}