I\'ve had a look at the codelab for WorkManager plus some examples on here, but everything in code I have seen is either related to doing work locally on the device or work uplo
This is initial thought. Somebody please correct me if i'm wrong.
my worker would already have posted that it was successful and it probably would not proceed with the callback, right?
we can use the callback from API reponse, to construct output Data of the worker and set it using worker.setOutputData()
Then listen to the LiveData<WorkStatus>
from workManager. From this workstatus we can get outputData using, workStatus.getOutputdata()
. This data can give us the API response we want.
We can pass this response to next worker in the worker chain to carry out tasks like updating local DB.
- Schedule a job that runs once a day in background
You can schedule a PeriodicWorkRequest
for that, which should be queued with enqueueUniquePeriodicWork
. This makes sure only one PeriodicWorkRequest
of a particular name can be active at a time.
Constraints constraint = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build();
PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(MyWorker.class, 1, TimeUnit.DAYS)
.setConstraints(constraint)
.build();
WorkManager workManager = WorkManager.getInstance();
workManager.enqueueUniquePeriodicWork("my_unique_worker", ExistingPeriodicWorkPolicy.KEEP, workRequest);
- The job is to do a data fetch from the REST API (and post it to a LiveData object if possible).
This can by done by sending your request synchronously within doWork()
of your worker. I wouldn't use LiveData
within your Worker
class. We come to that later. The API call would look with Retrofit for example like that:
@Override
public WorkerResult doWork() {
Call<MyData> call = APILayer.getInstance().fetchData();
Response<MyData> response = call.execute();
if (response.code() == 200) {
MyData data = response.body();
// ...
} else {
return Result.RETRY;
}
// ...
return Result.SUCCESS;
}
- When the data returns, check that it is newer than local data.
You fetched your API data in a synchronous way. Fetch your local data also synchronously and do whatever you need to do to compare them.
- Notify the user that new data is available.
If you schedule a task with WorkManager
it is guaranteed to run, even if your app is force-quit or the device is rebooted. So your task might complete while your app is not running. If you want to notify the user in any case you can send a notification. If you want to notify the user within a certain screen you can subscribe on your tasks status. For example like this (taken from the official guide):
WorkManager.getInstance().getStatusById(compressionWork.getId())
.observe(lifecycleOwner, workStatus -> {
// Do something with the status
if (workStatus != null && workStatus.getState().isFinished()) {
// ...
}
});
There's also getStatusesForUniqueWork(String uniqueWorkName)
for our example.
The official guide is also explaining how to return data from you Task with which you can call setValue()
on your MutableLiveData
for example.
I would propose to update your local data within your Worker
, subscribe on your workers status and once it succeeds update your UI with the local data (if you are not subscribed on your local data anyways, i.e. with Room and LiveData
).
Edit: In reference to point 4, reading status of periodic work requests works a little different. They are only switching between ENQUEUED
and RUNNING
until CANCELLED
. But will never have the state SUCCEEDED
or FAILED
. So listening for isFinished()
might not be what you are expecting.