WorkManager

WorkManger是一个单例对象, 但是从例子代码中没有看的调用初始化的地方。通过文档可知 WorkManager有两种初始化方式:

  1. 应用启动之后, 它自己自动初始化
  2. 按需初始化, 到了需要用到的地方才初始化。可以避免初始化影响应用的启动速度。

自动初始化

WorkManagerInitializer继承ContentProvider。在应用启动之后会调用 onCreate(), 所以自动初始化就是在 onCreate() 中执行WorkManager 的初始化。

1
2
3
4
5
6
7
8
9
public class WorkManagerInitializer extends ContentProvider {
    @Override
    public boolean onCreate() {
        // Initialize WorkManager with the default configuration.
      // 调用initialize方法进行初始化
        WorkManager.initialize(getContext(), new Configuration.Builder().build());
        return true;
    }
}

WorkManager

initialize()

1
2
3
4
//WorkManager.java
public static void initialize(@NonNull Context context, @NonNull Configuration configuration) {   //调用WorkManagerImpl的initialize()
    WorkManagerImpl.initialize(context, configuration);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
//WorkManagerImpl.java
public static void initialize(@NonNull Context context, @NonNull Configuration configuration) {
    synchronized (sLock) {
        if (sDelegatedInstance == null) {
            context = context.getApplicationContext();
            if (sDefaultInstance == null) {
                //创建WorkManagerImpl
                sDefaultInstance = new WorkManagerImpl(
                        context,
                        configuration,
                        new WorkManagerTaskExecutor(configuration.getTaskExecutor()));
            }
            sDelegatedInstance = sDefaultInstance;
        }
    }
}

WorkManagerImpl

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public WorkManagerImpl(
        @NonNull Context context,
        @NonNull Configuration configuration,
        @NonNull TaskExecutor workTaskExecutor,
        boolean useTestDatabase) {
    this(context,
            configuration,
            workTaskExecutor,
           //创建数据库
            WorkDatabase.create(
                    context.getApplicationContext(),
                    workTaskExecutor.getBackgroundExecutor(),
                    useTestDatabase)
    );
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
public WorkManagerImpl(
        @NonNull Context context,
        @NonNull Configuration configuration,
        @NonNull TaskExecutor workTaskExecutor,
        @NonNull WorkDatabase database) {
    Context applicationContext = context.getApplicationContext();
   //创建Scheduler
    List<Scheduler> schedulers =
            createSchedulers(applicationContext, configuration, workTaskExecutor);
    //创建Processor
    Processor processor = new Processor(
            context,
            configuration,
            workTaskExecutor,
            database,
            schedulers);
    //调用internalInit方法
    internalInit(context, configuration, workTaskExecutor, database, schedulers, processor);
}

createSchedulers()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public List<Scheduler> createSchedulers(
        @NonNull Context context,
        @NonNull Configuration configuration,
        @NonNull TaskExecutor taskExecutor) {
    return Arrays.asList(
            //调用Schedulers的createBestAvailableBackgroundScheduler方法
            Schedulers.createBestAvailableBackgroundScheduler(context, this),
            // Specify the task executor directly here as this happens before internalInit.
            // GreedyScheduler creates ConstraintTrackers and controllers eagerly.
            new GreedyScheduler(context, configuration, taskExecutor, this));
}

enqueue()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
//提交请求
public Operation enqueue(
        @NonNull List<? extends WorkRequest> workRequests) {
    // This error is not being propagated as part of the Operation, as we want the
    // app to crash during development. Having no workRequests is always a developer error.
    if (workRequests.isEmpty()) {
        throw new IllegalArgumentException(
                "enqueue needs at least one WorkRequest.");
    }
    return new WorkContinuationImpl(this, workRequests).enqueue();
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
@Override
public @NonNull Operation enqueue() {
    // Only enqueue if not already enqueued.
    //防止重复提交, mEnqueued 会在 EnqueueRunnable 中被标记为 true
    if (!mEnqueued) {
        // The runnable walks the hierarchy of the continuations
        // and marks them enqueued using the markEnqueued() method, parent first.
        EnqueueRunnable runnable = new EnqueueRunnable(this);
      	//EnqueueRunnable 被提交到线程池执行
        mWorkManagerImpl.getWorkTaskExecutor().executeOnBackgroundThread(runnable);
        mOperation = runnable.getOperation();
    } else {
       //...
    }
    return mOperation;
}

WorkRequest

image-20201208162244365

WorkRequestBuidler是一个抽象类, 一次性和周期任务分别实现了自己的 Buidler

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public abstract static class Builder<B extends Builder<?, ?>, W extends WorkRequest> {
    boolean mBackoffCriteriaSet = false;
    UUID mId;
    WorkSpec mWorkSpec;
    Set<String> mTags = new HashSet<>();
    Class<? extends ListenableWorker> mWorkerClass;
    Builder(@NonNull Class<? extends ListenableWorker> workerClass) {
        mId = UUID.randomUUID(); //分配一个uuid
        mWorkerClass = workerClass;
        mWorkSpec = new WorkSpec(mId.toString(), workerClass.getName());//创建WorkSpec
        addTag(workerClass.getName());//
    }
  	public final @NonNull W build() {
    	W returnValue = buildInternal();//子类实现buildInternal()
    	// Create a new id and WorkSpec so this WorkRequest.Builder can be used multiple times.
    	mId = UUID.randomUUID();
    	mWorkSpec = new WorkSpec(mWorkSpec);
    	mWorkSpec.id = mId.toString();
    	return returnValue;
		}
}

WorkSpec

查看WorkSpec的定义能发现其利用 Room 实现的数据库字段和类字段的映射。

在创建任务的时候, 每个任务会:

  • 分配一个 uuid
  • 创建一个 WorkSpec
  • 添加 Worker 的类名为 tag
  • 一次性任务设置 inputMergerClassName
  • 周期任务设置周期执行的间隔时间

EnqueueRunnable

run()

 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
//EnqueueRunnable
@Override
public void run() {
    try { // 判断 Worker 是否有循环引用
        if (mWorkContinuation.hasCycles()) {
            throw new IllegalStateException(
                    String.format("WorkContinuation has cycles (%s)", mWorkContinuation));
        }
      	//储存到数据库, 并返回是否需要执行
        boolean needsScheduling = addToDatabase();
        if (needsScheduling) {
          	//需要执行:
          	//启用 RescheduleReceiver: 一个广播接收器
            // Enable RescheduleReceiver, only when there are Worker's that need scheduling.
            final Context context =
                    mWorkContinuation.getWorkManagerImpl().getApplicationContext();
            PackageManagerHelper.setComponentEnabled(context, RescheduleReceiver.class, true);
          // 在后台执行 work
            scheduleWorkInBackground();
        }
        mOperation.setState(Operation.SUCCESS);
    } catch (Throwable exception) {
        mOperation.setState(new Operation.State.FAILURE(exception));
    }
}

addToDatabase()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
//添加到数据库
public boolean addToDatabase() {
    WorkManagerImpl workManagerImpl = mWorkContinuation.getWorkManagerImpl();
    WorkDatabase workDatabase = workManagerImpl.getWorkDatabase();
    workDatabase.beginTransaction();
    try {
        boolean needsScheduling = processContinuation(mWorkContinuation);
        workDatabase.setTransactionSuccessful();
        return needsScheduling;
    } finally {
        workDatabase.endTransaction();
    }
}

scheduleWorkInBackground()

1
2
3
4
5
6
7
8
public void scheduleWorkInBackground() {
    WorkManagerImpl workManager = mWorkContinuation.getWorkManagerImpl();
    //遍历Scheduler执行Scheduler的schedule()
    Schedulers.schedule(
            workManager.getConfiguration(),
            workManager.getWorkDatabase(),
            workManager.getSchedulers());
}

Schedulers

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
@NonNull
static Scheduler createBestAvailableBackgroundScheduler(
        @NonNull Context context,
        @NonNull WorkManagerImpl workManager) {
    Scheduler scheduler;
  // >=23 创建SystemJobScheduler
    if (Build.VERSION.SDK_INT >= WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL) {
        scheduler = new SystemJobScheduler(context, workManager);
      //调用PackageManagerHelper的静态方法
        setComponentEnabled(context, SystemJobService.class, true);
    } else {
        //创建GcmScheduler
        scheduler = tryCreateGcmBasedScheduler(context);
        if (scheduler == null) {
          //如果GcmScheduler为空则创建SystemAlarmScheduler
            scheduler = new SystemAlarmScheduler(context);
            setComponentEnabled(context, SystemAlarmService.class, true);
        }
    }
    return scheduler;
}

Scheduler

Scheduler

参考