场景
- 保证后台使命履行如上传,下载,同步数据等(不行作为保活的手段)
- 内部有对电量做了优化
- 履行延时的使命
运用
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);
调度器履行获取中心逻辑
-
addToDatabase() 添加到初始化完结的数据库内
获取builder 装备 -
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));
}
}
- 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进程的再次发动履行
- 在运用篇的时分咱们界说了网络约束,一起打包过程的时分体系协助主动注册了网络播送接收者,这也是退出进程再次翻开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>
- 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));
}
}
}
}
- 检查数据库的是否有有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从头履行,读取数据库信息再履行保证使命的准确性