I have my architecture like so:
Dao methods returning
Flow<T>:@Query("SELECT * FROM table WHERE id = :id") fun itemById(id: Int): Flow<Item>Repository layer returning items from DB but also backfilling from network:
(* Need help here -- this is not working as intended **)
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 layer taking the flow, applying any transformations, and converting it into a LiveData using .asLiveData():
fun observeItem(): LiveData<Item> = itemRepository.getItemFlow() .map { // apply transformation to view model } .asLiveData()Fragment observing LiveData emissions and updating UI:
viewModel.item().observeNotNull(viewLifecycleOwner) { renderUI(it) }
The issue I'm having is at step 2. I can't seem to figure out a way to structure the logic so that I can emit the items from Flow immediately, but also perform the network fetch without waiting.
Since the fetch from network logic is in the same suspend function it'll wait for the network request to finish before emitting the results downstream. But I just want to fire that request independently since I'm not interested in waiting for a result (when it comes back, it'll update Room and I'll get the results naturally).
Any thoughts?
EDIT
Marko's solution works well for me, but I did attempt a similar approach like so:
suspend fun items(): Flow<List<Cryptocurrency>> = coroutineScope {
launch {
itemApi.makeRequest().also { insert(it) }
}
itemDao.itemById(1)
}