Android知识总结
一、背景
1.1、特点
保证用户的任务一定会执行
记录更新每一个任务的信息/状态【Room数据库的更新】,手机重启,APP被杀掉 都一定会执行,因为同学们要记住一句话:Google说WorkManager是保证你的任务一定会执行的。非及时性的执行任务
就是不会马上执行,哪怕是你看到的现象是马上执行的,但每次执行的时间都无法确定,因为都是非及时性的执行任务哦。
1.2、适用场景:
定期重复性任务,但时效性/及时性要求不高的,例如:定期log上传,数据备份等。
1.3、使用
- Worker,用于数据互相传递
public class WorkManager2 extends Worker {
public static final String TAG = "WorkManager";
private WorkerParameters workerParams;
public WorkManager2(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
this.workerParams = workerParams;
}
// 后台任务 并且 异步的 (原理:线程池执行Runnable)
@NonNull
@Override
public Result doWork() {
// 开始执行了 ENQUEUED
Log.d(TAG, "WorkManager doWork: 后台任务执行了");
// 接收 Activity传递过来的数据
String name = workerParams.getInputData().getString("name");
Log.d(TAG, "WorkManager doWork: 接收MainActivity传递过来的数据: " + name);
// 正在执行中 RUNNING
// 反馈数据 给 Activity
// 把任务中的数据回传到Activity中
Data build = new Data.Builder().putString("name", "WorkManager2").build();
// return new Result.Failure(); // 本地执行 doWork 任务时 失败
// return new Result.Retry(); // 本地执行 doWork 任务时 重试一次
// return new Result.Success(); // 本地执行 doWork 任务时 成功 执行任务完毕
return Result.success(build);
}
}
- Activity
/**
* 数据 互相传递
*
* @param view
*/
public void testBackgroundWork2(View view) {
// 数据
Data data = new Data.Builder().putString("name", "WorkManagerActivity").build();
// 请求对象初始化
OneTimeWorkRequest build = new OneTimeWorkRequest.Builder(WorkManager2.class)
.setInputData(data)
.build();
// 一般都是通过 状态机 接收 WorkManager2的回馈数据
// 状态机(LiveData) 才能接收 WorkManager回馈的数据
WorkManager.getInstance(this).getWorkInfoByIdLiveData(build.getId())
.observe(this, new Observer() {
@Override
public void onChanged(WorkInfo workInfo) {
// ENQUEUED,RUNNING,SUCCEEED
Log.d(WorkManager2.TAG, "状态:" + workInfo.getState().name());
if (workInfo.getState().isFinished()) { // 判断成功 SUCCEEDED状态
Log.d(WorkManager2.TAG, "取到了任务回传的数据: "
+ workInfo.getOutputData().getString("name"));
}
}
});
WorkManager.getInstance(this).enqueue(build);
}
二、初始化源码
2.1、初始化
从这边 ContentProvider 开始执行,这是自动给我们加入的。
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public class WorkManagerInitializer extends ContentProvider {
@Override
public boolean onCreate() {
// Initialize WorkManager with the default configuration.
WorkManager.initialize(getContext(), new Configuration.Builder().build());
return true;
}
}
由于WorkManager
是个单例,在此时WorkManager
就已经被初始化了,在initialize()
之前,会创建一个默认的Configuration
,Configuration
设置了许多属性,用来管理和调度工作的方式,看initialize()的实现,由于WorkManager
是个抽象类
,真正的构造方法是在他的子类WorkManagerImpl
实现的。
- 执行
WorkManager#initialize
方法
public static void initialize(@NonNull Context context, @NonNull Configuration configuration) {
WorkManagerImpl.initialize(context, configuration);
}
- 在
WorkManager
的实现类WorkManagerImpl
中初始化
public static void initialize(@NonNull Context context, @NonNull Configuration configuration) {
synchronized (sLock) {
if (sDelegatedInstance != null && sDefaultInstance != null) {
throw new IllegalStateException("WorkManager is already initialized. Did you "
+ "try to initialize it manually without disabling "
+ "WorkManagerInitializer? See "
+ "WorkManager#initialize(Context, Configuration) or the class level "
+ "Javadoc for more information.");
}
//单例
if (sDelegatedInstance == null) {
context = context.getApplicationContext();
if (sDefaultInstance == null) {
//初始化 WorkManagerImpl
sDefaultInstance = new WorkManagerImpl(
context,
configuration,
new WorkManagerTaskExecutor(configuration.getTaskExecutor()));
}
sDelegatedInstance = sDefaultInstance;
}
}
}
此时sDelegatedInstance
为 null,WorkManager
会先创建一个默认的WorkManagerTaskExecutor
对象,用来执行WorkManager
的任务,下面创建一个WorkManagerImpl
对象:
- 在
WorkManagerImpl
中初始化
public WorkManagerImpl(
@NonNull Context context,
@NonNull Configuration configuration,
@NonNull TaskExecutor workTaskExecutor) {
this(context,
configuration,
workTaskExecutor,
context.getResources().getBoolean(R.bool.workmanager_test_configuration));
}
public WorkManagerImpl(
@NonNull Context context,
@NonNull Configuration configuration,
@NonNull TaskExecutor workTaskExecutor,
boolean useTestDatabase) {
this(context,
configuration,
workTaskExecutor,
WorkDatabase.create(
context.getApplicationContext(),
workTaskExecutor.getBackgroundExecutor(),
useTestDatabase)
);
}
在 WorkDatabase
中执行 create() 方法来创建ROOM
数据库。
public static WorkDatabase create(
@NonNull final Context context,
@NonNull Executor queryExecutor,
boolean useTestDatabase) {
RoomDatabase.Builder builder;
if (useTestDatabase) {
builder = Room.inMemoryDatabaseBuilder(context, WorkDatabase.class)
.allowMainThreadQueries();
} else {
String name = WorkDatabasePathHelper.getWorkDatabaseName();
builder = Room.databaseBuilder(context, WorkDatabase.class, name);
builder.openHelperFactory(new SupportSQLiteOpenHelper.Factory() {
@NonNull
@Override
public SupportSQLiteOpenHelper create(
@NonNull SupportSQLiteOpenHelper.Configuration configuration) {
SupportSQLiteOpenHelper.Configuration.Builder configBuilder =
SupportSQLiteOpenHelper.Configuration.builder(context);
configBuilder.name(configuration.name)
.callback(configuration.callback)
.noBackupDirectory(true);
FrameworkSQLiteOpenHelperFactory factory =
new FrameworkSQLiteOpenHelperFactory();
return factory.create(configBuilder.build());
}
});
}
return builder.setQueryExecutor(queryExecutor)
.addCallback(generateCleanupCallback())
.addMigrations(WorkDatabaseMigrations.MIGRATION_1_2)
.addMigrations(
new WorkDatabaseMigrations.RescheduleMigration(context, VERSION_2,
VERSION_3))
.addMigrations(MIGRATION_3_4) //版本升级
.addMigrations(MIGRATION_4_5)
.addMigrations(
new WorkDatabaseMigrations.RescheduleMigration(context, VERSION_5,
VERSION_6))
.addMigrations(MIGRATION_6_7)
.addMigrations(MIGRATION_7_8)
.addMigrations(MIGRATION_8_9)
.addMigrations(new WorkDatabaseMigrations.WorkMigration9To10(context))
.addMigrations(
new WorkDatabaseMigrations.RescheduleMigration(context, VERSION_10,
VERSION_11))
.fallbackToDestructiveMigration()
.build();
}
在这里就创建了数据库
,WorkDatabase.create()
将任务列表序列化到本地,记录每一个任务的属性,执行条件,执行顺序及执行状态等,从而保证任务在冷启动或硬件重启后,然后根据条件继续执行。
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public WorkManagerImpl(
@NonNull Context context,
@NonNull Configuration configuration,
@NonNull TaskExecutor workTaskExecutor,
@NonNull WorkDatabase database) {
Context applicationContext = context.getApplicationContext();
Logger.setLogger(new Logger.LogcatLogger(configuration.getMinimumLoggingLevel()));
//步骤一
List schedulers = createSchedulers(applicationContext, workTaskExecutor);
//步骤二
Processor processor = new Processor(
context,
configuration,
workTaskExecutor,
database,
schedulers);
//步骤三
internalInit(context, configuration, workTaskExecutor, database, schedulers, processor);
}
这里有三个重要的初始化步骤。
- 步骤一:createSchedulers()创建的Schedulers进行任务调度
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@NonNull
public List createSchedulers(
@NonNull Context context,
@NonNull TaskExecutor taskExecutor) {
//返回一个Scheduler数组。其中GreedyScheduler() 是实例化好了哦
return Arrays.asList(
Schedulers.createBestAvailableBackgroundScheduler(context, this),
// 埋下伏笔 GreedyScheduler贪婪调度程序
new GreedyScheduler(context, taskExecutor, this));
}
- 步骤二:Processor()用来管理Schedulers的执行。
public WorkManagerImpl(...) {
...
List schedulers = createSchedulers(applicationContext, workTaskExecutor);
Processor processor = new Processor(
context,
configuration,
workTaskExecutor,
database,
schedulers);
....
}
- 步骤三:internalInit()真正的初始化。先看createSchedulers()的实现。
private void internalInit(@NonNull Context context,
@NonNull Configuration configuration,
@NonNull TaskExecutor workTaskExecutor,
@NonNull WorkDatabase workDatabase,
@NonNull List schedulers,
@NonNull Processor processor) {
context = context.getApplicationContext();
mContext = context;
mConfiguration = configuration;
mWorkTaskExecutor = workTaskExecutor;
mWorkDatabase = workDatabase;
mSchedulers = schedulers;
mProcessor = processor;
mPreferenceUtils = new PreferenceUtils(workDatabase);
mForceStopRunnableCompleted = false;
// Checks for app force stops.
// 这里的 【检查应用程序强制停止】
//例如:正在执行任务的时候,手机关机了,或者发生了意外,这里就会重试之前失败的任务哦
mWorkTaskExecutor.executeOnBackgroundThread(new ForceStopRunnable(context, this));
}
- 任务是执行
ForceStopRunnable#run
方法
public class ForceStopRunnable implements Runnable {
private final Context mContext;
private final WorkManagerImpl mWorkManager;
public ForceStopRunnable(@NonNull Context context, @NonNull WorkManagerImpl workManager) {
mContext = context.getApplicationContext();
mWorkManager = workManager;
}
@Override
public void run() {
WorkDatabasePathHelper.migrateDatabase(mContext);
Logger.get().debug(TAG, "Performing cleanup operations.");
try {
boolean needsScheduling = cleanUp();
if (shouldRescheduleWorkers()) {
Logger.get().debug(TAG, "Rescheduling Workers.");
mWorkManager.rescheduleEligibleWork();
// Mark the jobs as migrated.
mWorkManager.getPreferenceUtils().setNeedsReschedule(false);
} else if (isForceStopped()) {
Logger.get().debug(TAG, "Application was force-stopped, rescheduling.");
mWorkManager.rescheduleEligibleWork();
} else if (needsScheduling) {
Logger.get().debug(TAG, "Found unfinished work, scheduling it.");
Schedulers.schedule(
mWorkManager.getConfiguration(),
mWorkManager.getWorkDatabase(),
mWorkManager.getSchedulers());
}
mWorkManager.onForceStopRunnableCompleted();
} catch (SQLiteCantOpenDatabaseException
| SQLiteDatabaseCorruptException
| SQLiteAccessPermException exception) {
String message =
"The file system on the device is in a bad state. WorkManager cannot access "
+ "the app's internal data store.";
Logger.get().error(TAG, message, exception);
throw new IllegalStateException(message, exception);
}
}
}
以上代码的Runnable的作用就是在WorkManager初始化过程中,发现了未完成的,需要重新执行的任务。
2.2、总结
WorkManager的初始化 总结:
① WorkManager的初始化是由WorkManagerInitializer这个ContentProvider执行的
② 会初始化 Configuration,WorkManagerTaskExecutor,WorkDatabase,Schedulers,Processor
③ GreedyScheduler 埋下伏笔
④ 发现了未完成的,需要重新执行的任务(之前 意外 中断 的继续执行)
三、非约束条件任务的执行源码
3.1、源码流程
- 开始执行
WorkManager.getInstance(this).enqueue(request)
进入WorkManager#enqueue
方法
public final Operation enqueue(@NonNull WorkRequest workRequest) {
return enqueue(Collections.singletonList(workRequest));
}
public abstract Operation enqueue(@NonNull List extends WorkRequest> requests);
- 执行
WorkManager
的实现类WorkManagerImpl
的实现方法
public Operation enqueue(
@NonNull List extends WorkRequest> workRequests) {
//请求 = null,抛出移出
if (workRequests.isEmpty()) {
throw new IllegalArgumentException(
"enqueue needs at least one WorkRequest.");
}
return new WorkContinuationImpl(this, workRequests).enqueue();
}
创建一个WorkContinuationImpl()
对象,再执行enqueue()
方法。WorkContinuationImpl
是WorkContinuation
的子类。
- 创建
WorkContinuationImpl
类
public class WorkContinuationImpl extends WorkContinuation {
private final WorkManagerImpl mWorkManagerImpl;
private final String mName;
private final ExistingWorkPolicy mExistingWorkPolicy;
private final List extends WorkRequest> mWork;
private final List mIds;
private final List mAllIds;
private final List mParents;
private boolean mEnqueued;
private Operation mOperation;
WorkContinuationImpl(
@NonNull WorkManagerImpl workManagerImpl,
@NonNull List extends WorkRequest> work) {
this(
workManagerImpl,
null,
ExistingWorkPolicy.KEEP,
work,
null);
}
WorkContinuationImpl(
@NonNull WorkManagerImpl workManagerImpl,
String name,
ExistingWorkPolicy existingWorkPolicy,
@NonNull List extends WorkRequest> work) {
this(workManagerImpl, name, existingWorkPolicy, work, null);
}
WorkContinuationImpl(@NonNull WorkManagerImpl workManagerImpl,
String name,
ExistingWorkPolicy existingWorkPolicy,
@NonNull List extends WorkRequest> work,
@Nullable List parents) {
mWorkManagerImpl = workManagerImpl;
mName = name;
mExistingWorkPolicy = existingWorkPolicy;
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);
}
}
}
WorkContinuation保存任务相关的所有信息,像这个 WorkManager,WorkRequest,父WorkContinuation ....
- 我们再接着继续看WorkContinuationImpl的enqueue()方法的实现:
WorkContinuationImpl#enqueue
方法
public @NonNull Operation enqueue() {
// Only enqueue if not already enqueued.
if (!mEnqueued) {
//包装 任务
EnqueueRunnable runnable = new EnqueueRunnable(this);
mWorkManagerImpl.getWorkTaskExecutor().executeOnBackgroundThread(runnable);
mOperation = runnable.getOperation();
} else {
Logger.get().warning(TAG,
String.format("Already enqueued work ids (%s)", TextUtils.join(", ", mIds)));
}
return mOperation;
}
WorkManager
的TaskExecutor
执行了EnqueueRunnable
,那么需要看EnqueueRunnable
的run
函数:
public class EnqueueRunnable implements Runnable {
private static final String TAG = Logger.tagWithPrefix("EnqueueRunnable");
private final WorkContinuationImpl mWorkContinuation;
private final OperationImpl mOperation;
public EnqueueRunnable(@NonNull WorkContinuationImpl workContinuation) {
mWorkContinuation = workContinuation;
mOperation = new OperationImpl();
}
@Override
public void run() {
try {
if (mWorkContinuation.hasCycles()) {
throw new IllegalStateException(
String.format("WorkContinuation has cycles (%s)", mWorkContinuation));
}
//addToDatabase()的作用是把WorkSpec存入到数据库,并对任务的状态进行校验
boolean needsScheduling = addToDatabase();
if (needsScheduling) {
// Enable RescheduleReceiver, only when there are Worker's that need scheduling.
final Context context =
mWorkContinuation.getWorkManagerImpl().getApplicationContext();
PackageManagerHelper.setComponentEnabled(context, RescheduleReceiver.class, true);
//下面重点就是看着这个函数了
scheduleWorkInBackground();
}
mOperation.setState(Operation.SUCCESS);
} catch (Throwable exception) {
mOperation.setState(new Operation.State.FAILURE(exception));
}
}
}
- 执行
EnqueueRunnable#scheduleWorkInBackground
方法
@VisibleForTesting
public void scheduleWorkInBackground() {
WorkManagerImpl workManager = mWorkContinuation.getWorkManagerImpl();
// 下面重点就是看着这个函数了
Schedulers.schedule(
workManager.getConfiguration(),
workManager.getWorkDatabase(),
workManager.getSchedulers());
}
下面 调用了Schedulers.schedule()方法,传入了Configuration, WorkDatabase, Scheduler这三个对象。执行schedule()函数:
Schedulers#schedule
// Schedulers.java 类
public static void schedule(
@NonNull Configuration configuration,
@NonNull WorkDatabase workDatabase,
List schedulers) {
if (schedulers == null || schedulers.size() == 0) {
return;
}
WorkSpecDao workSpecDao = workDatabase.workSpecDao();
List eligibleWorkSpecs;
//开始事务
workDatabase.beginTransaction();
try {
eligibleWorkSpecs = workSpecDao.getEligibleWorkForScheduling(
configuration.getMaxSchedulerLimit());
if (eligibleWorkSpecs != null && eligibleWorkSpecs.size() > 0) {
long now = System.currentTimeMillis();
for (WorkSpec workSpec : eligibleWorkSpecs) {
//先进行了一系列的数据库操作,然后开始根据条件每个任务进行调度,更新保存数据库等操作
workSpecDao.markWorkSpecScheduled(workSpec.id, now);
}
}
workDatabase.setTransactionSuccessful();
} finally {
//结束事务
workDatabase.endTransaction();
}
if (eligibleWorkSpecs != null && eligibleWorkSpecs.size() > 0) {
WorkSpec[] eligibleWorkSpecsArray = eligibleWorkSpecs.toArray(new WorkSpec[0]);
// Delegate to the underlying scheduler.
for (Scheduler scheduler : schedulers) {
// scheduler.schedule()对每个任务进行调度处理,我们是没有约束的一次性任务,所以看一下GreedyScheduler对于schedule()方法的实现
scheduler.schedule(eligibleWorkSpecsArray);
}
}
}
- 回到上面初始化创建的
GreedyScheduler
类中的schedule
方法
// GreedyScheduler.java 类 贪婪调度程序执行 schedule
@Override
public void schedule(@NonNull WorkSpec... workSpecs) {
if (mIsMainProcess == null) {
// The default process name is the package name.
mIsMainProcess = TextUtils.equals(mContext.getPackageName(), getProcessName());
}
if (!mIsMainProcess) {
Logger.get().info(TAG, "Ignoring schedule request in non-main process");
return;
}
registerExecutionListenerIfNeeded();
List constrainedWorkSpecs = new ArrayList<>();
List constrainedWorkSpecIds = new ArrayList<>();
for (WorkSpec workSpec : workSpecs) {
if (workSpec.state == WorkInfo.State.ENQUEUED
&& !workSpec.isPeriodic()
&& workSpec.initialDelay == 0L
&& !workSpec.isBackedOff()) {
if (workSpec.hasConstraints()) {
if (SDK_INT >= 23 && workSpec.constraints.requiresDeviceIdle()) {
// Ignore requests that have an idle mode constraint.
Logger.get().debug(TAG,
String.format("Ignoring WorkSpec %s, Requires device idle.",
workSpec));
} else if (SDK_INT >= 24 && workSpec.constraints.hasContentUriTriggers()) {
// Ignore requests that have content uri triggers.
Logger.get().debug(TAG,
String.format("Ignoring WorkSpec %s, Requires ContentUri triggers.",
workSpec));
} else {
constrainedWorkSpecs.add(workSpec);
constrainedWorkSpecIds.add(workSpec.id);
}
} else {
Logger.get().debug(TAG, String.format("Starting work for %s", workSpec.id));
// 由于无约束条件,所以进入此else阶段 的startWork这个函数
mWorkManagerImpl.startWork(workSpec.id);
}
}
}
// onExecuted() which is called on the main thread also modifies the list of mConstrained
// WorkSpecs. Therefore we need to lock here.
synchronized (mLock) {
if (!constrainedWorkSpecs.isEmpty()) {
Logger.get().debug(TAG, String.format("Starting tracking for [%s]",
TextUtils.join(",", constrainedWorkSpecIds)));
mConstrainedWorkSpecs.addAll(constrainedWorkSpecs);
mWorkConstraintsTracker.replace(mConstrainedWorkSpecs);
}
}
}
- 执行
WorkManagerImpl#startWork
方法
public void startWork(@NonNull String workSpecId) {
startWork(workSpecId, null);
}
// WorkManagerImpl.java 类
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public void startWork(
@NonNull String workSpecId,
@Nullable WorkerParameters.RuntimeExtras runtimeExtras) {
// WorkTaskExecutor对任务进行了调度,下面进入StartWorkRunnable的run()的实现,
//切入后台线程
mWorkTaskExecutor
.executeOnBackgroundThread(
new StartWorkRunnable(this, workSpecId, runtimeExtras));
}
- 看
StartWorkRunnable
类
public class StartWorkRunnable implements Runnable {
private WorkManagerImpl mWorkManagerImpl;
private String mWorkSpecId;
private WorkerParameters.RuntimeExtras mRuntimeExtras;
public StartWorkRunnable(
WorkManagerImpl workManagerImpl,
String workSpecId,
WorkerParameters.RuntimeExtras runtimeExtras) {
mWorkManagerImpl = workManagerImpl;
mWorkSpecId = workSpecId;
mRuntimeExtras = runtimeExtras;
}
@Override
public void run() {
//将任务的信息交给Processor,由Processor调用startWork()去执行任务,下面进入Processor类:
mWorkManagerImpl.getProcessor().startWork(mWorkSpecId, mRuntimeExtras);
}
}
- 进入
Processor#startWork
方法
public boolean startWork(
@NonNull String id,
@Nullable WorkerParameters.RuntimeExtras runtimeExtras) {
WorkerWrapper workWrapper;
synchronized (mLock) {
if (mEnqueuedWorkMap.containsKey(id)) {
Logger.get().debug(
TAG,
String.format("Work %s is already enqueued for processing", id));
return false;
}
//创建WorkerWrapper 任务
workWrapper =
new WorkerWrapper.Builder(
mAppContext,
mConfiguration,
mWorkTaskExecutor,
this,
mWorkDatabase,
id)
.withSchedulers(mSchedulers)
.withRuntimeExtras(runtimeExtras)
.build();
ListenableFuture future = workWrapper.getFuture();
future.addListener(
new FutureListener(this, id, future),
mWorkTaskExecutor.getMainThreadExecutor());
mEnqueuedWorkMap.put(id, workWrapper);
}
//创建了一个WorkerWrapper的Runnable对象,交由WorkTaskExecutor调度处理。
//WorkerWrapper的run()方法的实现,下面就要进入 WorkerWrapper类了
mWorkTaskExecutor.getBackgroundExecutor().execute(workWrapper);
Logger.get().debug(TAG, String.format("%s: processing %s", getClass().getSimpleName(), id));
return true;
}
- 进入
WorkerWrapper#run
方法
// WorkerWrapper.java类
@WorkerThread
@Override
public void run() {
mTags = mWorkTagDao.getTagsForWorkSpecId(mWorkSpecId);
mWorkDescription = createWorkDescription(mTags);
// 下面会进入此函数哦
runWorker();
}
//WorkerWrapper.java类
private void runWorker() {
if (tryCheckForInterruptionAndResolve()) {
return;
}
mWorkDatabase.beginTransaction();
try {
mWorkSpec = mWorkSpecDao.getWorkSpec(mWorkSpecId);
...
mWorkDatabase.setTransactionSuccessful();
} finally {
mWorkDatabase.endTransaction();
}
// Merge inputs. This can be potentially expensive code, so this should not be done inside
// a database transaction.
...
WorkerParameters params = new WorkerParameters(
UUID.fromString(mWorkSpecId),
input,
mTags,
mRuntimeExtras,
mWorkSpec.runAttemptCount,
mConfiguration.getExecutor(),
mWorkTaskExecutor,
mConfiguration.getWorkerFactory(),
new WorkProgressUpdater(mWorkDatabase, mWorkTaskExecutor),
new WorkForegroundUpdater(mForegroundProcessor, mWorkTaskExecutor));
// Not always creating a worker here, as the WorkerWrapper.Builder can set a worker override
// in test mode.
if (mWorker == null) {
mWorker = mConfiguration.getWorkerFactory().createWorkerWithDefaultFallback(
mAppContext,
mWorkSpec.workerClassName,
params);
}
...
// Try to set the work to the running state. Note that this may fail because another thread
// may have modified the DB since we checked last at the top of this function.
if (trySetRunning()) {
if (tryCheckForInterruptionAndResolve()) {
return;
}
final SettableFuture future = SettableFuture.create();
// Call mWorker.startWork() on the main thread.
//进入主线程
mWorkTaskExecutor.getMainThreadExecutor()
.execute(new Runnable() {
@Override
public void run() {
try {
Logger.get().debug(TAG, String.format("Starting work for %s",
mWorkSpec.workerClassName));
//我们看到调用了mWorker.startWork()方法
mInnerFuture = mWorker.startWork();
future.setFuture(mInnerFuture);
} catch (Throwable e) {
future.setException(e);
}
}
});
// Avoid synthetic accessors.
...
}
- 执行
Worker#startWork
方法
//需要自己实现的抽象方法
public abstract @NonNull Result doWork();
@Override
public final @NonNull ListenableFuture startWork() {
mFuture = SettableFuture.create();
getBackgroundExecutor().execute(new Runnable() {
@Override
public void run() {
try {
// 此doWork函数 就是调用自定义的Workr
Result result = doWork();
mFuture.set(result);
} catch (Throwable throwable) {
mFuture.setException(throwable);
}
}
});
return mFuture;
}
同学们,这就是我们自己写的,自定义任务:
public class UploadWorker extends Worker {
private final static String TAG = UploadWorker.class.getSimpleName();
public UploadWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@NonNull
@Override
public Result doWork() {
Log.d(TAG, "doWork: run ... ");
return Result.success();
}
}
3.2、总结
WorkManager的 无约束的任务的执行源码 总结:
- WorkManager执行了enqueue()后,创建WorkContinuationImpl对象执行enqueue()方法。
- WorkContinuationImpl持有的EnqueueRunnable对象将任务添加到db,并交给Schedulers去调度。
- Schedulers将任务交给每一个Scheduler去处理,GreedyScheduler会先处理这个任务。
- GreedyScheduler经过一系列判断后,调用WorkManager的startWork()方法执行这种一次性,非延迟,无约束的任务。
- WorkManager持有的StartWorkRunnable对象会将任务交给Processor去处理,执行startWork()方法。
- Processor创建一个WorkerWrapper对象,由它去调用Worker的startWork()方法。
四、有约束条件任务的执行源码
WorkManager的有约束条件任务的执行源码:(非低电量才能执行)
4.1、源码分析
当在电量变化时,收到BATTERY_LOW
的广播,在BatteryNotLowProxy
的onReceive()
进行处理:
// ConstraintProxy.java 类 约束代理广播接收者类
abstract class ConstraintProxy extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Logger.get().debug(TAG, String.format("onReceive : %s", intent));
Intent constraintChangedIntent = CommandHandler.createConstraintsChangedIntent(context);
context.startService(constraintChangedIntent);
}
}
- 执行
CommandHandler#createConstraintsChangedInten
方法
// ConstraintProxy.java类
static Intent createConstraintsChangedIntent(@NonNull Context context) {
Intent intent = new Intent(context, SystemAlarmService.class);
intent.setAction(ACTION_CONSTRAINTS_CHANGED);
return intent;
}
- 会启动此服务
SystemAlarmService
,执行onStartCommand()
方法处理如下:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
... ...
if (intent != null) {
// 调用了SystemAlarmDispatcher.add()方法
mDispatcher.add(intent, startId);
}
return Service.START_REDELIVER_INTENT;
}
SystemAlarmDispatcher#add
//SystemAlarmDispatcher
@MainThread
public boolean add(@NonNull final Intent intent, final int startId) {
//检测线程
assertMainThread();
String action = intent.getAction();
if (TextUtils.isEmpty(action)) {
Logger.get().warning(TAG, "Unknown command. Ignoring");
return false;
}
if (CommandHandler.ACTION_CONSTRAINTS_CHANGED.equals(action)
&& hasIntentWithAction(CommandHandler.ACTION_CONSTRAINTS_CHANGED)) {
return false;
}
intent.putExtra(KEY_START_ID, startId);
synchronized (mIntents) {
boolean hasCommands = !mIntents.isEmpty();
mIntents.add(intent);
if (!hasCommands) {
// 方法中执行了processCommand()
processCommand();
}
}
return true;
}
private void assertMainThread() {
if (mMainHandler.getLooper().getThread() != Thread.currentThread()) {
throw new IllegalStateException("Needs to be invoked on the main thread.");
}
}
// SystemAlarmDispatcher.java 类
private void processCommand() {
assertMainThread();
PowerManager.WakeLock processCommandLock =
WakeLocks.newWakeLock(mContext, PROCESS_COMMAND_TAG);
try {
processCommandLock.acquire();
// Process commands on the background thread.
mWorkManager.getWorkTaskExecutor().executeOnBackgroundThread(new Runnable() {
@Override
public void run() {
synchronized (mIntents) {
mCurrentIntent = mIntents.get(0);
}
if (mCurrentIntent != null) {
final String action = mCurrentIntent.getAction();
final int startId = mCurrentIntent.getIntExtra(KEY_START_ID,
DEFAULT_START_ID);
Logger.get().debug(TAG,
String.format("Processing command %s, %s", mCurrentIntent,
startId));
final PowerManager.WakeLock wakeLock = WakeLocks.newWakeLock(
mContext,
String.format("%s (%s)", action, startId));
try {
Logger.get().debug(TAG, String.format(
"Acquiring operation wake lock (%s) %s",
action,
wakeLock));
wakeLock.acquire();
// 这个代码就是核心,等下下面我们就要分析
mCommandHandler.onHandleIntent(mCurrentIntent, startId,
SystemAlarmDispatcher.this);
} catch (Throwable throwable) {
Logger.get().error(
TAG,
"Unexpected error in onHandleIntent",
throwable);
} finally {
Logger.get().debug(
TAG,
String.format(
"Releasing operation wake lock (%s) %s",
action,
wakeLock));
wakeLock.release();
// Check if we have processed all commands
postOnMainThread(
new DequeueAndCheckForCompletion(SystemAlarmDispatcher.this));
}
}
}
});
} finally {
processCommandLock.release();
}
}
- 执行
CommandHandler#onHandleIntent
方法,action为ACTION_CONSTRAINTS_CHANGED
//CommandHandler 类
if (ACTION_CONSTRAINTS_CHANGED.equals(action)) {
handleConstraintsChanged(intent, startId, dispatcher);
}
//CommandHandler.java 类
private void handleConstraintsChanged(
@NonNull Intent intent, int startId,
@NonNull SystemAlarmDispatcher dispatcher) {
ConstraintsCommandHandler changedCommandHandler =
new ConstraintsCommandHandler(mContext, startId, dispatcher);
changedCommandHandler.handleConstraintsChanged();
}
创建一个action为ACTION_DELAY_MET的Intent然后由SystemAlarmDispatcher发送出去,实际上也是调用了SystemAlarmDispatcher.add()方法,注意会回到SystemAlarmDispatcher的add()流程哦:
//ConstraintsCommandHandler
void handleConstraintsChanged() {
...
for (WorkSpec workSpec : eligibleWorkSpecs) {
String workSpecId = workSpec.id;
Intent intent = CommandHandler.createDelayMetIntent(mContext, workSpecId);
mDispatcher.postOnMainThread(
new SystemAlarmDispatcher.AddRunnable(mDispatcher, intent, mStartId));
}
mWorkConstraintsTracker.reset();
}
- 调用
CommandHandler#createDelayMetIntent
创建 Intent
static Intent createDelayMetIntent(@NonNull Context context, @NonNull String workSpecId) {
Intent intent = new Intent(context, SystemAlarmService.class);
intent.setAction(ACTION_DELAY_MET);
intent.putExtra(KEY_WORKSPEC_ID, workSpecId);
return intent;
}
当再次回到onHandleIntent()
方法,在CommandHandler
的onHandleIntent()
方法中,action为ACTION_DELAY_MET
的执行是。
// CommandHandler.java 类
else if (ACTION_DELAY_MET.equals(action)) {
handleDelayMet(intent, startId, dispatcher);
}
handleDelayMet()
的执行过程,会调用DelayMetCommandHandler
的handleProcessWork()
方法,接着执行onAllConstraintsMet()
:
@Override
public void onAllConstraintsMet(@NonNull List workSpecIds) {
... ...
synchronized (mLock) {
if (mCurrentState == STATE_INITIAL) {
// 这里就是我们前面分析的流程,就不进行详解了
... ...
boolean isEnqueued = mDispatcher.getProcessor().startWork(mWorkSpecId);
... ...
} else {
Logger.get().debug(TAG, String.format("Already started work for %s", mWorkSpecId));
}
}
}