I'm working on an application that uses WorkerManager for background tasks, most of the time it's used to send requests to the backend and process the received data, I thought it would be a great idea to use LiveData (or Flow) to automatically update UI after new data is saved to the database, but it doesn't work as i expected, the flow does not emit data after it saved to the db
In my background worker, I have an async method that loads the data to backend after the user clicks the "save" button.
override suspend fun doWorkWithRetry(): Result = coroutineScope {
val one = processCreatedReceipts()
if (one.await() * other async methods *) {
Result.success()
} else {
throw RuntimeException("Failed to upload data")
}
}
@OptIn(DelicateCoroutinesApi::class)
private fun processCreatedReceipts() = GlobalScope.async {
val data: List<Expenses> = expensesRepo.findAllBySyncState(SyncState.UNSYNCED)
data.parallelStream().forEach { expense ->
val dto = expense.asCreateDto()
expensesService.createReceipt(dto).run { r, t ->
t?.let {
expensesRepo.updateSyncStateById(expense.id, SyncState.SYNC_FAILED)
throw RuntimeException("Data sync failed with error: ${t.message}")
}
r?.data?.result?.let { result ->
* save to received data to db *
}
}
}
}
From the UI I get the list of data as a flow using this method in the DAO object
@Query(
"""
SELECT *
FROM files
WHERE resourceId == :id and sync_state is not 'PENDING_DELETE'
"""
)
abstract fun findByIdFlow(id: String?): Flow<List<FileData>>
I create a Flow inside a Fragments viewModel using
val list: Flow<List<FileData>> = repo.findByIdFlow(userId)
And I collect data in a fragment using
lifecycleScope.launch(Dispatchers.IO) {
viewModel.list.collect {
lifecycleScope.launch(Dispatchers.Main) {
* update UI *
}
}
}
Could this be a problem with the async methods what saved data to db or am I getting the data from db in wrong way?
val list: Flow<List<ExpensesWithFile>> = repo.findWithFile(userId)I collect data inside fragment in that waylifecycleScope.launch(Dispatchers.IO) { viewModel.list.collect { lifecycleScope.launch(Dispatchers.Main) { * update UI method * } } }