[TOC]
前言
Jetpack中的WorkManager用于管理后台运行的任务,可替代原先由Service执行的后台任务。
使用
Gradle
gradle引入
1
|
implementation "androidx.work:work-runtime-ktx:$work_version"
|
Worker
实现Worker接口。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class MyWork(
var appContext: Context,
var workerParams: WorkerParameters
): Worker(appContext, workerParams) {
override fun doWork(): Result {
// TODO:执行任务的详细内容
/**
* 返回执行结果
* 执行成功:Result.success()
* 执行失败:Result.failure()
* 稍后重试:Result.retry()
*/
return Result.success()
}
}
|
WorkerRequest
运用Worker构造任务请求WorkRequest
1
2
3
4
5
6
|
/**
* WorkerRequest两种类型
* OneTimeWorkRequest:一次性任务
* PeriodicWorkRequest:周期性任务
*/
var myWorkRequest: OneTimeWorkRequest = OneTimeWorkRequestBuilder<MyWorker>().build()
|
WorkerManager
将任务添加到WorkerManager的队列中
1
2
|
// 获取WorkManager实例(单例模式),并将任务添加到WorkManager的队列中
WorkManager.getInstance(context).enqueue(myWorkRequest)
|
进入队列源码解析
我们解析“添加任务”过程的源码。
1
|
WorkManager.getInstance(context).enqueue(myWorkRequest)
|
获取WorkManager实例
WorkManager是一个抽象类,我们在获取WorkManager实例的时候获取到的是它的实现类WorkManagerImpl:
1
2
3
4
5
6
|
// WorkManager.java
// WorkManager获取实例的方法
public static @NonNull WorkManager getInstance(@NonNull Context context) {
return WorkManagerImpl.getInstance(context);
}
|
enqueue()添加任务请求
拿到实例后,我们将任务请求WorkRequest请求传入enqueue()方法,有两个主要的enqueue()方法:
WorkManager中实现的enqueue(@NonNull WorkRequest workRequest):用于添加一个任务请求。
WorkManagerImpl中实现的equeue(@NonNull List<? extends WorkRequest> workRequests):用于添加一组任务请求。
WorkManager中的enqueue()
1
2
3
4
5
6
7
8
9
|
// WorkManager
@NonNull
public final Operation enqueue(@NonNull WorkRequest workRequest) {
// 调用了下面的enqueue(@NonNull List<? extends WorkRequest> requests)
return enqueue(Collections.singletonList(workRequest));
}
@NonNull
public abstract Operation enqueue(@NonNull List<? extends WorkRequest> requests);
|
可见,即便是添加一个任务请求WorkRequest,这个任务请求依然会被转化为任务请求列表List<WorkRequest,实际上执行的依然是enqueue(@NonNull List<? extends WorkRequest> requests),而这个方法在WorkManagerImpl中被实现了。
WorkManagerImpl中的enqueue()
在WorkManagerImpl中我们实现了enqueue(@NonNull List<? extends WorkRequest> requests),该方法执行了WorkContinuationImpl(即WorkContinuation的实现类)的enqueue():
1
2
3
4
5
6
7
8
9
10
|
// WorkManagerImpl.java
@Override
@NonNull
public Operation enqueue(
@NonNull List<? extends WorkRequest> workRequests
) {
...
return new WorkContinuationImpl(this, workRequests).enqueue();
}
|
WorkContinuation
我们并不清楚在WorkContinuation是什么,我们在WorkContinuation.java的头部注释看到这样的解释内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/*
* <pre>
* A C
* | |
* B D
* | |
* +-------+
* |
* E </pre>
*
* you would write the following:
*
* <pre>
* {@code
* WorkContinuation left = workManager.beginWith(A).then(B);
* WorkContinuation right = workManager.beginWith(C).then(D);
* WorkContinuation final = WorkContinuation.combine(Arrays.asList(left, right)).then(E);
* final.enqueue();}</pre>
*/
|
显而易见,WorkContinuation是用于任务排序用的。
在WorkManagerImpl中会首先构造WorkContinuation:
1
2
3
4
5
6
7
8
9
10
11
|
WorkContinuationImpl(
@NonNull WorkManagerImpl workManagerImpl,
@NonNull List<? extends WorkRequest> work) {
this(
workManagerImpl,
null,
ExistingWorkPolicy.KEEP,
work, // 传入List<WorkRequest>
null
);
}
|
调用了以下构造方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
WorkContinuationImpl(
@NonNull WorkManagerImpl workManagerImpl,
String name,
ExistingWorkPolicy existingWorkPolicy,
@NonNull List<? extends WorkRequest> work,
@Nullable List<WorkContinuationImpl> parents
) {
mWorkManagerImpl = workManagerImpl;
mName = name;
mExistingWorkPolicy = existingWorkPolicy;
// List<WorkRequest>最终被传入mWork
mWork = work;
mParents = parents;
mIds = new ArrayList<>(mWork.size());
mAllIds = new ArrayList<>();
if (parents != null) {
for (WorkContinuationImpl parent : parents) {
mAllIds.addAll(parent.mAllIds);
}
}
for (int i = 0; i < work.size(); i++) {
String id = work.get(i).getStringId();
mIds.add(id);
mAllIds.add(id);
}
}
|
我们传入的WorkRequest最终被传递到WorkContinuation的mWork这个队列中。
构造完成后,执行WorkContinuation中的enqueue():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@Override
public @NonNull Operation enqueue() {
...
if(!mEnqueued) {
EnqueueRunnable runnable = new EnqueueRunnable(this);
mWorkManagerImpl
.getWorkTaskExecutor()
.executeOnBackgroundThread(runnable);
mOperation = runnable.getOperation();
} else {
...
}
return mOperation;
}
|
他调用了WorkManagerImpl中的任务执行器WorkTaskExecutor将我们传入的任务调到后台线程中执行。
1
2
3
|
mWorkManagerImpl
.getWorkTaskExecutor()
.executeOnBackgroundThread(runnable);
|
总结
Worker定义任务内容,WorkerRequest定义任务请求,WorkerManager管理任务的执行,WorkContinuation管理任务的顺序。
- 无论是添加一个任务请求
Workquest还是一组任务请求List<WorkRequest>,执行的都是WorkManagerImpl中添加一组任务请求的方法enqueue(@NonNull List<? extends WorkRequest> requests)。
- 任务最终会被
WorkManagerImpl中的WorkTaskExecutor调用到后台线程中执行。
代码的主体逻辑如下:
