Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

WorkManager: Awaiting work does not seem to wait for work to finish?

I am trying to start a work request to fetch data from a remote source then insert the data into a Room database.

The worker handles fetching and inserting data into the Room database.

In the repository, I enqueue a work request for WorkManager:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

// ...

private val workManager = WorkManager.getInstance(context)

private val imageDao = database.imageDao()

suspend fun getImages(): List<Images> {

    // ...
    
    workManager.apply {
        enqueueUniqueWork(
            uniqueWorkName,
            ExistingWorkPolicy.KEEP,
            OneTimeWorkRequestBuilder<FetchImagesWorker>()
                .setConstraints(constraints)
                .build()
        )
            .await()
    }

    return imageDao.getAll()
}

The work request runs successfully. However, the function attempts to access the Room database in the line return imageDao.getAll() before the work request returns Success.

I use await() on the unique work from this example.

However, it does not seem to make a difference having await() or not. Also, the work in the Worker class is within a withContext(Dispatchers.IO) block, but again, it does not seem to make a difference if it’s there or not.

Any ideas how I can await the work request to finish before the function returns the results from the Room database?

Thanks in advance.

EDIT:

Return a Flow<List<Image>> instead of List<Image>.

Then:

val workStatesFlow = workManager.getWorkInfosForUniqueWorkLiveData(uniqueWorkName).asFlow()
workStatesFlow.map { workInfos -> workInfos.first().state }.collect { workState ->
    when (workState) -> {
        WorkInfo.State.SUCCEEDED -> {
            emit(imageDao.getAll())
        }
        else -> {}
    }
}

>Solution :

The issue with your code is that the call to enqueue the work request is asynchronous, meaning that it will not block the thread and will continue executing the next lines of code. This is why you are experiencing the issue of attempting to access the Room database before the work request completes.

To await the completion of the work request before accessing the Room database, you need to use a LiveData object that the Worker can update when it completes the task. Then, you can observe this LiveData object from your repository or ViewModel, and return the Room database results only when the LiveData object is updated with the result of the work request.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading