场景

  1. 保证后台使命履行如上传,下载,同步数据等(不行作为保活的手段)
  2. 内部有对电量做了优化
  3. 履行延时的使命

运用

public class MainWorker extends Worker {
    public final static String TAG = MainWorker7.class.getSimpleName();
    // 有结构函数
    public MainWorker7(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }
    @SuppressLint("RestrictedApi")
    @NonNull
    @Override
    public Result doWork() {
        Log.d(TAG, "MainWorker doWork: 后台使命履行了 started");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new Result.Success(); // 本地履行 doWork 使命时 成功 履行使命完毕
    }
}

使命需要承继 Worker,并且是异步操作

// 约束条件
Constraints constraints = new Constraints.Builder()
        .setRequiredNetworkType(NetworkType.CONNECTED) // 约束条件,必须是网络连接
        .build();
// 构建Request
OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(MainWorker7.class)
        .setConstraints(constraints)
        .build();
// 加入队列
WorkManager.getInstance(this).enqueue(request);

履行,app 存活的时分履行操作,下次翻开使命必定履行

初始化

WorkManger 的初始化在打车apk 的时分动态生成了四大组件的provider

<provider
    android:name="androidx.work.impl.WorkManagerInitializer"
    android:exported="false"
    android:multiprocess="true"
    android:authorities="com.derry.workmanagersimple.workmanager-init"
    android:directBootAware="false" />

运用Android 最常用的结构者规划形式进行初始化

WorkManager.initialize(getContext(), new Configuration.Builder().build());

初始化了,装备,异步线程池,和数据库,数据库创建是非常重要是使命再次履行的要害TAG

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public WorkManagerImpl(
        @NonNull Context context,
        @NonNull Configuration configuration,
        @NonNull TaskExecutor workTaskExecutor,
        boolean useTestDatabase) {
    this(context,
            configuration,
            workTaskExecutor,
            WorkDatabase.create(
                    context.getApplicationContext(),
                    workTaskExecutor.getBackgroundExecutor(),
                    useTestDatabase)
    );
}

履行使命

履行使命异步的EnqueueRunnable

WorkManager.getInstance(this).enqueue(request);
EnqueueRunnable runnable = new EnqueueRunnable(this);
mWorkManagerImpl.getWorkTaskExecutor().executeOnBackgroundThread(runnable);

调度器履行获取中心逻辑

  1. addToDatabase() 添加到初始化完结的数据库内
    获取builder 装备

  2. scheduleWorkInBackground() 调度到后台作业


EnqueueRunnable
@Override
public void run() {
   try {
       if (mWorkContinuation.hasCycles()) {
           throw new IllegalStateException(
                   String.format("WorkContinuation has cycles (%s)", mWorkContinuation));
       }
       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));
   }
}
  1. Schedulers.schedule 履行调度作业
@VisibleForTesting
public void scheduleWorkInBackground() {
    WorkManagerImpl workManager = mWorkContinuation.getWorkManagerImpl();
    Schedulers.schedule(
            workManager.getConfiguration(),
            workManager.getWorkDatabase(),
            workManager.getSchedulers());
}

4. 调度器履行 GreedySchedule WorkManagerImp startWork(调度器形式/策略形式)

public void startWork(
        @NonNull String workSpecId,
        @Nullable WorkerParameters.RuntimeExtras runtimeExtras) {
    mWorkTaskExecutor
            .executeOnBackgroundThread(
                    new StartWorkRunnable(this, workSpecId, runtimeExtras));
}
StartWorkRunnable--mWorkManagerImpl.getProcessor().startWork(mWorkSpecId, mRuntimeExtras);

5. workWrapper mWorker.startWork() 终究会调用到 Worker的doWork 咱们运用篇承继的便是Worker 终究构成闭环履行,首尾呼应

Processor().startWork
WorkerWrapper workWrapper;
mWorkTaskExecutor.getBackgroundExecutor().execute(workWrapper);
workWrapper.runWorker()
mWorkTaskExecutor.getMainThreadExecutor()
        .execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Logger.get().debug(TAG, String.format("Starting work for %s",
                            mWorkSpec.workerClassName));
                    mInnerFuture = mWorker.startWork();
                    future.setFuture(mInnerFuture);
                } catch (Throwable e) {
                    future.setException(e);
                }
            }
        });
`
 Worker 履行doWork()

发动使命后退出app进程的再次发动履行

  1. 在运用篇的时分咱们界说了网络约束,一起打包过程的时分体系协助主动注册了网络播送接收者,这也是退出进程再次翻开app使命再次履行的发起点
receiver
    android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$NetworkStateProxy"
    android:enabled="false"
    android:exported="false"
    android:directBootAware="false">
    <intent-filter>
        <action
            android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
</receiver>
  1. ConstraintProxy 发动服务 SystemAlarmService 体系服务
@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);
}
static Intent createConstraintsChangedIntent(@NonNull Context context) {
    Intent intent = new Intent(context, SystemAlarmService.class);
    intent.setAction(ACTION_CONSTRAINTS_CHANGED);
    return intent;
}

3 分发器准备作业,替换TAG为ACTION_DELAY_MET 履行
handleDelayMet(intent, startId, dispatcher);

SystemAlarmService
mDispatcher.add(intent, startId);
SystemAlarmDispatcher
processCommand();
mCommandHandler.onHandleIntent(mCurrentIntent, startId,
    SystemAlarmDispatcher.this);
CommandHandler
void onHandleIntent(
    @NonNull Intent intent,
    int startId,
    @NonNull SystemAlarmDispatcher dispatcher) {
  String action = intent.getAction();
  if (*ACTION_CONSTRAINTS_CHANGED*.equals(action)) {
    handleConstraintsChanged(intent, startId, dispatcher); // 替换 Tag 符号为 *ACTION_DELAY_MET*
  } else if (*ACTION_RESCHEDULE*.equals(action)) {
    handleReschedule(intent, startId, dispatcher);
  } else {
    Bundle extras = intent.getExtras();
    if (!*hasKeys*(extras, *KEY_WORKSPEC_ID*)) {
      Logger.*get*().error(*TAG*,
          String.*format*("Invalid request for %s, requires %s.",
              action,
              *KEY_WORKSPEC_ID*));
    } else {
      if (*ACTION_SCHEDULE_WORK*.equals(action)) {
        handleScheduleWorkIntent(intent, startId, dispatcher);
      } else if (*ACTION_DELAY_MET*.equals(action)) { // 替换符号后履行
        handleDelayMet(intent, startId, dispatcher);
      } else if (*ACTION_STOP_WORK*.equals(action)) {
        handleStopWork(intent, dispatcher);
      } else if (*ACTION_EXECUTION_COMPLETED*.equals(action)) {
        handleExecutionCompleted(intent, startId);
      } else {
        Logger.*get*().warning(*TAG*, String.*format*("Ignoring intent %s", intent));
      }
    }
  }
}
  1. 检查数据库的是否有有id,履行 startWork 回到履行使命的逻辑
delayMetCommandHandler.handleProcessWork();
void handleProcessWork() {
  mWakeLock = WakeLocks.*newWakeLock*(
      mContext,
      String.*format*("%s (%s)", mWorkSpecId, mStartId));
  Logger.*get*().debug(*TAG*,
      String.*format*("Acquiring wakelock %s for WorkSpec %s", mWakeLock, mWorkSpecId));
  mWakeLock.acquire();
  WorkSpec workSpec = mDispatcher.getWorkManager()
      .getWorkDatabase()
      .workSpecDao()
      .getWorkSpec(mWorkSpecId);
  // 这儿获取了mWorkSpecId 数据库,为后续获取使命信息
  // This should typically never happen. Cancelling work should remove alarms, but if an
  // alarm has already fired, then fire a stop work request to remove the pending delay met
  // command handler.
  if (workSpec == null) {
    stopWork();
    return;
  }
  // Keep track of whether the WorkSpec had constraints. This is useful for updating the
  // state of constraint proxies when onExecuted().
  mHasConstraints = workSpec.hasConstraints();
  if (!mHasConstraints) {
    Logger.*get*().debug(*TAG*, String.*format*("No constraints for %s", mWorkSpecId));
    onAllConstraintsMet(Collections.*singletonList*(mWorkSpecId));
  } else {
    // Allow tracker to report constraint changes
    mWorkConstraintsTracker.replace(Collections.*singletonList*(workSpec));
  }
}
mDispatcher.getProcessor().startWork(mWorkSpecId);
mWorkTaskExecutor.getBackgroundExecutor().execute(workWrapper);
mDispatcher.getProcessor().startWork(mWorkSpecId);
mWorkTaskExecutor.getBackgroundExecutor().execute(workWrapper);

总结

存储使命相关装备,存储是永久性装备,也是必定会履行使命的要害点,不管是马上履行还是从头翻开app从头履行,读取数据库信息再履行保证使命的准确性