WorkManager 是jetpack 家族中非常重要的一环
针对 WorkManager 所使用的场景有一下几种 1: 立即执行 ,可以使用加急策
2: 周期性任务
3:各种约束条件性的任务
下面写一个比较简单的任务,我们来看一下他的使用
// 创建约束条件
val constraints=Constraints.Builder()
// .setRequiresDeviceIdle(true)//空闲
// .setRequiredNetworkType(NetworkType.CONNECTED)// 链接网络
// .setRequiresBatteryNotLow(true)//不是低电量
// .setRequiresCharging(true)//是否充电
// .setRequiresStorageNotLow(true)//磁盘空间是否充足
.build()
// 为任务设置参数
var dataInput= Data.Builder().putString("tsm","1111").build();
// 创建任务 单次任务, PeriodicWorkRequestBuilder 为周期性任务
var oneTimeWorkRequest= PeriodicWorkRequestBuilder<TsmWork1>(1,TimeUnit.DAYS)
.setConstraints(constraints)//设置约束条件
.setInputData(dataInput)
// .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)// 加急策略,没有加急配额,加急任务回退成普通任务,也可以将任务丢弃
.build()
// 使用LiveData 监听任务状态,同时获取 任务执行结果
WorkManager.getInstance(this).getWorkInfoByIdLiveData(oneTimeWorkRequest.id).observe(this){workInfo->
// 需要根据任务状态来判断是否可以获取到单数, 这个方法会多次调用,只有成功会返回 Data,
if(workInfo.state ==WorkInfo.State.SUCCEEDED){
var result = workInfo.outputData.getBoolean("tsm",false)
}
}
//如果周期性任务重复添加,那么就会出现在一个运行周期内,这个任务被执行了多次
// 这里就是不希望重复添加相同的任务,可以使用这个方法, WorkManager.getInstance(this).enqueueUniquePeriodicWork("tsmTag",ExistingPeriodicWorkPolicy.KEEP,oneTimeWorkRequest)
这里在使用过程中有一个非常需要注意的点,那就是周期性任务重复添加的问题,使用WorkManager.getInstance(this).enqueueUniquePeriodicWork 这个方法可以规避
WorkManager.getInstance(this).getWorkInfosForUniqueWorkLiveData("tsmTag1").observe(this){
it.forEach { item->
Log.i("tian.shm","getWorkInfosByTagLiveData:${item.id}")
}
}
使用上面代码可以查看周期性任务是否存在,并且根据实际情况来判断是否更新这个任务
我在刚开始看源码的时候,WorkManager.getInstance(this)第一次调用是我主动发起的,但是在查看官方文档的时候发现,他会在app启动的时候自动执行初始化的操作,我们来看他是如何执行的
这里有一个非常重要的关键点那就是在使用了WorkManager 之后, 会向你的App 中添加非常多的 service prvoider receiver 等标签
service 标签可以执行后台任务
prvoider 可以让WorkManager 被他人唤醒
receiver 可以接收到电量 网络等状态
大致的粘贴几个上来
<service
android:name="androidx.work.impl.background.gcm.WorkManagerGcmService"
android:directBootAware="false"
android:exported="@bool/enable_gcm_scheduler_default"
android:permission="com.google.android.gms.permission.BIND_NETWORK_TASK_SERVICE" >
<intent-filter>
<action android:name="com.google.android.gms.gcm.ACTION_TASK_READY" />
</intent-filter>
</service>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="com.tsm.tsmworkmananger.androidx-startup"
android:exported="false" >
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup" />
</provider>
<service
android:name="androidx.work.impl.background.systemalarm.SystemAlarmService"
android:directBootAware="false"
android:enabled="@bool/enable_system_alarm_service_default"
android:exported="false" />
这个AndroidManifast 文件可以使用 Analyze Apk 这个插件来看,但是我这边不可以,但是我们可以在 /build/intermediates/merged_manifest/debug 这个目录下看到他, 从代码上可以看到,我们注册了一个 provider,那么他的执行时机就一定是 Application 的生命周期方法之前,先来看看 WorkManagerInitializer 这个类干了什么
//Initializes WorkManager using androidx.startup.
public final class WorkManagerInitializer implements Initializer<WorkManager> {
private static final String TAG = Logger.tagWithPrefix("WrkMgrInitializer");
@NonNull
@Override
public WorkManager create(@NonNull Context context) {
// Initialize WorkManager with the default configuration.
Logger.get().debug(TAG, "Initializing WorkManager with default configuration.");
WorkManager.initialize(context, new Configuration.Builder().build());
return WorkManager.getInstance(context);
}
@NonNull
@Override
public List<Class<? extends androidx.startup.Initializer<?>>> dependencies() {
return Collections.emptyList();
}
}
一个段非常简单的代码就是初始化了 WorkManager ,这也就代表着 WorkManager 的初始化工作肯定不是由我们的 WorkManager.getInstance(this).enqueue 等操作来初始化的,而且初始化的是 WorkManagerImpl ,可以看到 WorkManagerImpl 是 WorkManager 的代理实现类
那么他在初始化完成时,都做了哪些操作呢
private void internalInit(@NonNull Context context,
@NonNull Configuration configuration,
@NonNull TaskExecutor workTaskExecutor,
@NonNull WorkDatabase workDatabase,
@NonNull List<Scheduler> schedulers,
@NonNull Processor processor) {
context = context.getApplicationContext();
mContext = context;
mConfiguration = configuration;
//任务线程池
mWorkTaskExecutor = workTaskExecutor;
// 任务查找是通过Room 来完成的
mWorkDatabase = workDatabase;
// 调度
mSchedulers = schedulers;
// 智能的安排和执行
mProcessor = processor;
mPreferenceUtils = new PreferenceUtils(workDatabase);
mForceStopRunnableCompleted = false;
// Check for direct boot mode
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && context.isDeviceProtectedStorage()) {
throw new IllegalStateException("Cannot initialize WorkManager in direct boot mode");
}
// 强制停止执行
mWorkTaskExecutor.executeOnBackgroundThread(new ForceStopRunnable(context, this));
}
关于各个模块都负责哪些功能,可以根据主线流程后续查看,