WorkManager可以轻松设置和安排精心设计的任务请求。您可以将API用于以下场景:
链式任务
您的应用可能需要按特定顺序运行多个任务。 WorkManager
允许您创建和排队指定多个任务的工作序列,以及它们应运行的顺序。
例如,假设您的应用程序有三个 OneTimeWorkRequest
对象:workA
,workB
,和 workC
。任务必须按该顺序运行。要将它们排入队列,请使用该WorkManager.beginWith(OneTimeWorkRequest)
方法创建一个序列 ,并传递第一个OneTimeWorkRequest
对象; 该方法返回一个WorkContinuation
对象,该对象定义了一系列任务。然后OneTimeWorkRequest
按顺序添加剩余的对象, WorkContinuation.then(OneTimeWorkRequest)
最后将整个序列排入队列 WorkContinuation.enqueue()
:
WorkManager.getInstance()
.beginWith(workA)
// Note: WorkManager.beginWith() returns a
// WorkContinuation object; the following calls are
// to WorkContinuation methods
.then(workB) // FYI, then() returns a new WorkContinuation instance
.then(workC)
.enqueue();
在WorkManager
运行中所要求的顺序执行这些任务,根据每个任务的指定的约束。如果任何任务返回Result.failure()
,则整个序列结束。
您还可以将多个OneTimeWorkRequest
对象传递给任何 beginWith(List<OneTimeWorkRequest>)
和then(List<OneTimeWorkRequest>)
调用。如果将多个OneTimeWorkRequest
对象传递给单个方法调用,则在WorkManager
运行序列的其余部分之前运行所有这些任务(并行)。例如:
WorkManager.getInstance()
// First, run all the A tasks (in parallel):
.beginWith(Arrays.asList(workA1, workA2, workA3))
// ...when all A tasks are finished, run the single B task:
.then(workB)
// ...then run the C tasks (in any order):
.then(Arrays.asList(workC1, workC2))
.enqueue();
您可以通过使用WorkContinuation.combine(List<OneTimeWorkRequest>)
方法连接多个链来创建更复杂的序列。例如,假设您要运行如下序列:
图1.您可以使用 WorkContinuation
设置复杂的链式任务。
要设置此序列,请创建两个单独的链,然后将它们连接到第三个链中:
WorkContinuation chain1 = WorkManager.getInstance()
.beginWith(workA)
.then(workB);
WorkContinuation chain2 = WorkManager.getInstance()
.beginWith(workC)
.then(workD);
WorkContinuation chain3 = WorkContinuation
.combine(Arrays.asList(chain1, chain2))
.then(workE);
chain3.enqueue();
高级WorkManager主题
WorkManager可以轻松设置和安排精心设计的任务请求。您可以将API用于以下场景:
链式任务
您的应用可能需要按特定顺序运行多个任务。 WorkManager
允许您创建和排队指定多个任务的工作序列,以及它们应运行的顺序。
例如,假设您的应用程序有三个 OneTimeWorkRequest
对象:workA
,workB
,和 workC
。任务必须按该顺序运行。要将它们排入队列,请使用该WorkManager.beginWith(OneTimeWorkRequest)
方法创建一个序列 ,并传递第一个OneTimeWorkRequest
对象; 该方法返回一个WorkContinuation
对象,该对象定义了一系列任务。然后OneTimeWorkRequest
按顺序添加剩余的对象, WorkContinuation.then(OneTimeWorkRequest)
最后将整个序列排入队列 WorkContinuation.enqueue()
:
科特林
JAVA的
WorkManager.getInstance()
.beginWith(workA)
// Note: WorkManager.beginWith() returns a
// WorkContinuation object; the following calls are
// to WorkContinuation methods
.then(workB) // FYI, then() returns a new WorkContinuation instance
.then(workC)
.enqueue();
在WorkManager
运行中所要求的顺序执行这些任务,根据每个任务的指定的约束。如果任何任务返回Result.failure()
,则整个序列结束。
您还可以将多个OneTimeWorkRequest
对象传递给任何 beginWith(List<OneTimeWorkRequest>)
和then(List<OneTimeWorkRequest>)
调用。如果将多个OneTimeWorkRequest
对象传递给单个方法调用,则在WorkManager
运行序列的其余部分之前运行所有这些任务(并行)。例如:
科特林
JAVA的
WorkManager.getInstance()
// First, run all the A tasks (in parallel):
.beginWith(Arrays.asList(workA1, workA2, workA3))
// ...when all A tasks are finished, run the single B task:
.then(workB)
// ...then run the C tasks (in any order):
.then(Arrays.asList(workC1, workC2))
.enqueue();
您可以通过使用WorkContinuation.combine(List<OneTimeWorkRequest>)
方法连接多个链来创建更复杂的序列。例如,假设您要运行如下序列:
图1.您可以使用 WorkContinuation
设置复杂的链式任务。
要设置此序列,请创建两个单独的链,然后将它们连接到第三个链中:
WorkContinuation chain1 = WorkManager.getInstance()
.beginWith(workA)
.then(workB);
WorkContinuation chain2 = WorkManager.getInstance()
.beginWith(workC)
.then(workD);
WorkContinuation chain3 = WorkContinuation
.combine(Arrays.asList(chain1, chain2))
.then(workE);
chain3.enqueue();
在这种情况下,之前WorkManager
运行。它之前也运行过。后两者与已经完成, 运行。workA
workB
workC
workD
workB
workD
WorkManager
workE
注意:虽然WorkManager
按顺序运行每个子链,但无法保证任务chain1
可能与其中的任务重叠chain2
。例如,workB
可能在之前或之后运行workC
,或者它们可能同时运行。唯一的承诺是每个子链中的任务将按顺序运行; 也就是说,workB
直到workA
完成后才开始。
这些方法有许多变体WorkContinuation
可以为特定情况提供缩写。有关详细信息,请参阅 WorkContinuation
参考。
独特的工作顺序
您可以通过调用 而不是开始序列 来创建唯一的工作序列。每个独特的工作序列都有一个名称; 在只允许使用该名称一次一个工作序列。创建新的唯一工作序列时,如果已存在具有相同名称的未完成序列,则指定应执行的操作:beginUniqueWork(String, ExistingWorkPolicy, OneTimeWorkRequest)
beginWith(OneTimeWorkRequest)
WorkManager
WorkManager
如果您的任务不应多次排队,则唯一的工作顺序非常有用。例如,如果您的应用需要将其数据同步到网络,您可以将名为“sync”的序列排队,并指定如果已经有一个具有该名称的序列,则应忽略您的新任务。如果您需要逐步建立一长串任务,那么独特的工作顺序也很有用。例如,照片编辑应用程序可能允许用户撤消一长串操作。每个撤消操作可能需要一段时间,但必须以正确的顺序执行。在这种情况下,应用程序可以创建“撤消”链并根据需要将每个撤消操作附加到链。
输入参数和返回值
为了获得更大的灵活性,您可以将参数传递给任务并让任务返回结果。传递和返回的值是键值对。要将参数传递给任务,请在WorkRequest.Builder.setInputData(Data)
创建WorkRequest
对象之前调用该 方法。该方法采用Data
您创建的对象 Data.Builder
。本Worker
类可以通过调用访问这些参数 Worker.getInputData()
。要输出返回值,任务应将其包括在内Result
(例如,返回 Result.success(Data)
。您可以通过观察任务获得输出WorkInfo
。
例如,假设您有一个Worker
执行耗时计算的类。以下代码显示了Worker
该类的外观:
// Define the Worker class:
public class MathWorker extends Worker {
// Define the parameter keys:
public static final String KEY_X_ARG = "X";
public static final String KEY_Y_ARG = "Y";
public static final String KEY_Z_ARG = "Z";
// ...and the result key:
public static final String KEY_RESULT = "result";
public MathWorker(
@NonNull Context context,
@NonNull WorkerParameters params) {
super(context, params);
}
@Override
public Result doWork() {
// Fetch the arguments (and specify default values):
int x = getInputData().getInt(KEY_X_ARG, 0);
int y = getInputData().getInt(KEY_Y_ARG, 0);
int z = getInputData().getInt(KEY_Z_ARG, 0);
// ...do the math...
int result = myCrazyMathFunction(x, y, z);
//...set the output, and we're done!
Data output = new Data.Builder()
.putInt(KEY_RESULT, result)
.build();
return Result.success(output);
}
}
要创建工作并传递参数,您可以使用如下代码:
// Create the Data object:
Data myData = new Data.Builder()
// We need to pass three integers: X, Y, and Z
.putInt(KEY_X_ARG, 42)
.putInt(KEY_Y_ARG, 421)
.putInt(KEY_Z_ARG, 8675309)
// ... and build the actual Data object:
.build();
// ...then create and enqueue a OneTimeWorkRequest that uses those arguments
OneTimeWorkRequest mathWork = new OneTimeWorkRequest.Builder(MathWorker.class)
.setInputData(myData)
.build();
WorkManager.getInstance().enqueue(mathWork);
返回的值将在任务中可用WorkInfo
:
WorkManager.getInstance().getWorkInfoByIdLiveData(mathWork.getId())
.observe(lifecycleOwner, info -> {
if (info != null && info.getState().isFinished()) {
int myResult = info.getOutputData().getInt(KEY_RESULT,
myDefaultValue));
// ... do something with the result ...
}
});
如果链接任务,则一个任务的输出可用作链中下一个任务的输入。如果它是一个简单的链,只有一个OneTimeWorkRequest
后跟另一个 OneTimeWorkRequest
,第一个任务通过调用返回其结果Result.success(Data)
,下一个任务通过调用获取该结果 getInputData()
。如果链更复杂 - 例如,因为几个任务都将输出发送到单个后续任务 - 您可以定义一个InputMerger
on OneTimeWorkRequest.Builder
来指定如果不同任务返回具有相同键的输出会发生什么。
其他资源
WorkManager
是一个Android Jetpack架构组件。在Sunflower 演示应用程序中查看它的使用情况。