Workers: They Do Work
The work that you want to have done in the background needs to be wrapped in a Worker
subclass. This is an abstract
class with one abstract
method: doWork()
. In that method, you put your work to be done in the background.
Note that:
-
doWork()
is called after theWorkManager
engine has obtained a wakelock, so you do not need to acquire one yourself to ensure that the work can get done without the device falling asleep -
doWork()
is called on a background thread, so you do not need to fork one yourself -
doWork()
needs to return aListenableWorker.Result
object indicating if the work succeeded or failed, sodoWork()
should not be starting other background threads (directly or through libraries) -
doWork()
cannot run forever — at best, it might run for 10 minutes beforeJobScheduler
terminates it, and it is possible that it will have less time than that
As noted above, doWork()
returns a ListenableWorker.Result
object. There are static factory methods on ListenableWorker.Result
that you use to create instances. Those factory methods represent three main result scenarios:
-
success()
, which is what you are hoping for -
retry()
, which indicates that for one reason or another you could not do the work but would likeWorkManager
to retry the work in a little while -
failure()
, which indicates that the work could not be done and a later retry is likely to fail as well, so you are giving up
Beyond the return value and the aforementioned limitations on what you can do in doWork()
, the actual business logic is up to you.
For example, in the Work/Download
sample project, there is a DownloadWorker
class that downloads a file using OkHttp and Okio:
package com.commonsware.android.work.download;
import android.content.Context;
import android.support.annotation.NonNull;
import android.util.Log;
import java.io.File;
import java.io.IOException;
import androidx.work.ListenableWorker;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okio.BufferedSink;
import okio.Okio;
public class DownloadWorker extends Worker {
public static final String KEY_URL="url";
public static final String KEY_FILENAME="filename";
public DownloadWorker(@NonNull Context context,
@NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@NonNull
@Override
public Result doWork() {
OkHttpClient client=new OkHttpClient();
Request request=new Request.Builder()
.url(getInputData().getString(KEY_URL))
.build();
try (Response response=client.newCall(request).execute()) {
File dir=getApplicationContext().getCacheDir();
File downloadedFile=
new File(dir, getInputData().getString(KEY_FILENAME));
BufferedSink sink=Okio.buffer(Okio.sink(downloadedFile));
sink.writeAll(response.body().source());
sink.close();
}
catch (IOException e) {
Log.e(getClass().getSimpleName(), "Exception downloading file", e);
return ListenableWorker.Result.failure();
}
return ListenableWorker.Result.success();
}
}
Worker
— from which DownloadWorker
inherits — has a two-parameter constructor, taking a Context
and a WorkerParameters
object. In many cases, you can just chain to the superclass constructor, as DownloadWorker
does.
Pretty much everything inside of doWork()
is just application code that does the download and returns success()
if the download succeeded or failure()
if there was some exception during the download.
This doWork()
method is using two methods that we get from Worker
:
-
getApplicationContext()
, which works like the similarly-named method onContext
, returning you theApplication
singleton, in case you need aContext
-
getInputData()
, which we will examine more closely later in the chapter
Prev Table of Contents Next
This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.