I'm using a PeriodicWorkRequest for getting some data from the internet every hour. I would like to update the UI of my app with the Result returned by the worker. This is the code I have now:
workManager.enqueueUniquePeriodicWork("name", ExistingPeriodicWorkPolicy.REPLACE, work)
workManager
.getWorkInfoByIdLiveData(work.id)
.observe(this, { workInfo ->
if (workInfo?.state == WorkInfo.State.SUCCEEDED) {
// it never arrives here for updating the UI
}
}
Given the life cycle of a periodic work, the state SUCCEEDED
is never reached, as it bounces between RUNNING
and ENQUEUED
; in these two states the Result.OutputData
object is empty, so I cannot use it.
The app is thought not to be kept open all the time, but when it's opened it should show the last data retrieved from the worker.
How can I retrieve the OutputData of the Result returned by the doWork()
function? Is a periodic work the right tool for my use case?
In your case an option would be to persist the result data right when each work gets completed, so you can read it from any point. You've got several options, for example the jetpack DataStore.
A more elegant solution is to observe for LiveData changes which you publish from the Work itself. See getWorkInfosByTagLiveData.
The reason the output data is empty, as you already discovered, is due to the nature of the PeriodicWorkRequest, which will "chain->execute" jobs without final states, resulting in the next flow:
ENQUEUED >> RUNNING >> ENQUEUED >> RUNNING >> ...
In contrast, a OneTimeWorkRequest will be as as next, which includes a final state:
ENQUEUED >> RUNNING >> (SUCCEEDED or FAILED)
As stated in the WorkInfo documentation:
Note that output is only available for the terminal states (WorkInfo.State.SUCCEEDED and WorkInfo.State.FAILED)
Logically the output data will always be empty for PeriodicWorkRequests, being the only workaround to persist the desired data somewhere.