通过上一篇文,Android Jetpack组件之WorkManager后台任务管理的介绍与使用(一)_蜗牛、Z的博客-CSDN博客
我们可以弄清楚workmanager从接入到使用的基本流程。基本可以满足我们日常。那只是简单的入门。如果遇到更复杂的功能,那简单的就无法满足。
WorkManager.getInstance(requireContext()).enqueue(myWork)
唯一工作既可用于一次性工作,也可用于定期工作。您可以通过调用以下方法之一创建唯一工作序列,具体取决于您是调度重复工作还是一次性工作
String
。enum
可告知 WorkManager:如果已有使用该名称且尚未完成的唯一工作链,应执行什么操作。如需了解详情,请参阅冲突解决政策。WorkRequest
。对于一次性工作,您需要提供一个 ExistingWorkPolicy,它支持用于处理冲突的 4 个选项。
现有工作将成为新工作的先决条件。如果现有工作变为 CANCELLED
或 FAILED
状态,新工作也会变为 CANCELLED
或 FAILED
。如果您希望无论现有工作的状态如何都运行新工作,请改用 APPEND_OR_REPLACE
。
APPEND
,不过它并不依赖于先决条件工作状态。即使现有工作变为 CANCELLED
或 FAILED
状态,新工作仍会运行。对于定期工作,您需要提供一个 ExistingPeriodicWorkPolicy,它支持 REPLACE
和 KEEP
这两个选项。这些选项的功能与其对应的 ExistingWorkPolicy 功能相同。
在将工作加入队列后,您可以随时按其 name
、id
或与其关联的 tag
在 WorkManager 中进行查询,以检查其状态
//by uuid workManager.getWorkInfoById(syncWorker.id) // ListenableFuture// by name workManager.getWorkInfosForUniqueWork("sync") // ListenableFuture >// by tag workManager.getWorkInfosByTag("syncTag") // ListenableFuture
>
利用每个方法的 LiveData 变种,您可以通过注册监听器来观察 WorkInfo
的变化
val resultData = WorkManager.getInstance(application).getWorkInfoByIdLiveData(id)resultData.observe(this) {if (it?.state == WorkInfo.State.SUCCEEDED) {//}}
WorkManager 2.4.0 及更高版本支持使用 WorkQuery 对象对已加入队列的作业进行复杂查询。WorkQuery 支持按工作的标记、状态和唯一工作名称的组合进行查询。
val workQuery = WorkQuery.Builder.fromTags(listOf("one1")).addStates(listOf(WorkInfo.State.FAILED, WorkInfo.State.CANCELLED)).addUniqueWorkNames(listOf("preProcess", "sync")).build()val workInfos = WorkManager.getInstance(application).getWorkInfos(workQuery)
WorkQuery
中的每个组件(标记、状态或名称)与其他组件都是 AND
逻辑关系。组件中的每个值都是 OR
逻辑关系
例如:(name1 OR name2 OR ...) AND (tag1 OR tag2 OR ...) AND (state1 OR state2 OR ...)
// by id
workManager.cancelWorkById(build.id)// by name
workManager.cancelUniqueWork("sync")// by tag
workManager.cancelAllWorkByTag("syncTag")
正在运行的 Worker
可能会由于以下几种原因而停止运行:
WorkManager.cancelWorkById(UUID)
取消)。WorkRequest
加入到了队列中。旧的 WorkRequest
会立即被视为已取消。在您的工作器停止后,WorkManager 会立即调用 ListenableWorker.onStopped(),您可以调用 ListenableWorker.isStopped() 方法以检查工作器是否已停止
WorkManager 为设置和观察工作器的中间进度添加了一流的支持。如果应用在前台运行时,工作器保持运行状态,那么也可以使用返回 WorkInfo 的 LiveData 的 API 向用户显示此信息
只有在 ListenableWorker 运行时才能观察到和更新进度信息。如果尝试在 ListenableWorker 完成执行后在其中设置进度,则将会被忽略。您还可以使用 getWorkInfoBy…() 或 getWorkInfoBy…LiveData() 方法来观察进度信息。这两个方法会返回 WorkInfo 的实例,后者有一个返回 Data 的新 getProgress() 方法
对于使用 ListenableWorker 或 Worker 的 Java 开发者,setProgressAsync() API 会返回 ListenableFuture
class MyCoroutineWorker(appContext: Context,params: WorkerParameters
) : CoroutineWorker(appContext, params) {companion object {const val Progress = "Progress"private const val delayDuration = 1L}override suspend fun doWork(): Result {val firstUpdate = workDataOf(Progress to 0)val lastUpdate = workDataOf(Progress to 100)setProgress(firstUpdate)delay(delayDuration)setProgress(lastUpdate)return Result.Success.success()}override suspend fun getForegroundInfo(): ForegroundInfo {val id = Random.nextInt(0, Int.MAX_VALUE)return ForegroundInfo(id, getNotion())}private fun getNotion(): Notification {val notification = Notification()return notification;}
}
val liveData =WorkManager.getInstance(application).getWorkInfoByIdLiveData(coroutineWorker.id)liveData.observe(this, Observer { workinfo: WorkInfo? ->if (workinfo != null) {val datta = workinfo.progressval state = workinfo.stateif (datta != null && datta.size() > 0) {}}})
workDataOf(Progress to 0):
workDataOf是Data类里面的,workDataOf直接返回data对象,有因为这个data的存储是Map,所以Progress to 0=map(key,value)=map(Progress ,0)
在LiveData的observe(this)中,it.progress是Data对象,直接通过map对象去获取
val coroutineWorker= PeriodicWorkRequestBuilder(20, TimeUnit.MINUTES).build()WorkManager.getInstance(application).enqueue(coroutineWorker)
可以使用 WorkManager 创建工作链并将其加入队列。工作链用于指定多个依存任务并定义这些任务的运行顺序。当您需要以特定顺序运行多个任务时
如需创建工作链,您可以使用 WorkManager.beginWith(OneTimeWorkRequest) 或 WorkManager.beginWith(List
然后,可以使用 WorkContinuation 通过 then(OneTimeWorkRequest) 或 then(ListWorkContinuation.then(...)
都会返回一个新的 WorkContinuation
实例。如果添加了 OneTimeWorkRequest
实例的 List
,这些请求可能会并行运行
最后,您可以使用 WorkContinuation.enqueue() 方法对 WorkContinuation 工作链执行 enqueue() 操作
如下:
val work= OneTimeWorkRequest.from(MyWorks::class.java)WorkManager.getInstance(application).beginWith(work);WorkManager.getInstance(application).beginWith(work).then(work).then(work);
这种顺序类似属性动画一样,后面按顺序执行。
当您链接 OneTimeWorkRequest
实例时,父级工作请求的输出将作为子级的输入传入。因此,在上面的示例中,plantName1
、plantName2
和 plantName3
的输出将作为 cache
请求的输入传入。
WorkManager 提供两种不同类型的 InputMerger
:
OverwritingInputMerger 会尝试将所有输入中的所有键添加到输出中。如果发生冲突,它会覆盖先前设置的键。
ArrayCreatingInputMerger 会尝试合并输入,并在必要时创建数组
OverwritingInputMerger
是默认的合并方法。如果合并过程中存在键冲突,键的最新值将覆盖生成的输出数据中的所有先前版本。如果每种植物的输入都有一个与其各自变量名称("plantName1"
、"plantName2"
和 "plantName3"
)匹配的键,传递给 cache
工作器的数据将具有三个键值对。如果存在冲突,那么最后一个工作器将在争用中“取胜”,其值将传递给 cache。
由于工作请求是并行运行的,因此无法保证其运行顺序。在上面的示例中,plantName1
可以保留值 "tulip"
或 "elm"
,具体取决于最后写入的是哪个值。如果有可能存在键冲突,并且您需要在合并器中保留所有输出数据,那么 ArrayCreatingInputMerger
可能是更好的选择。
将每个键与数组配对。如果每个键都是唯一的,您会得到一系列一元数组,如果存在任何键冲突,那么所有对应的值会分组到一个数组中。
要工作成功完成(即,返回 Result.success()
),OneTimeWorkRequest
链便会按顺序执行。运行时,工作请求可能会失败或被取消,这会对依存工作请求产生下游影响。
当第一个 OneTimeWorkRequest
被加入工作请求链队列时,所有后续工作请求会被屏蔽,直到第一个工作请求的工作完成为止。
在加入队列且满足所有工作约束后,第一个工作请求开始运行。如果工作在根 OneTimeWorkRequest
或 List
中成功完成(即返回 Result.success()
),系统会将下一组依存工作请求加入队列。
如果该重试政策未定义或已用尽,或者您以其他方式已达到 OneTimeWorkRequest
返回 Result.failure()
的某种状态,该工作请求和所有依存工作请求都会被标记为 FAILED。
OneTimeWorkRequest
被取消时遵循相同的逻辑。任何依存工作请求也会被标记为 CANCELLED
,并且无法执行其工作。
如果要向已失败或已取消工作请求的链附加更多工作请求,新附加的工作请求也会分别标记为 FAILED
或 CANCELLED
。如果您想扩展现有链的工作,请参阅 ExistingWorkPolicy 中的 APPEND_OR_REPLACE
。
如需确定工作器未正确运行的原因,查看详细的 WorkManager 日志很有帮助。如需启用日志记录功能,您需要使用自定义初始化。首先,通过创建应用了清单合并规则 remove
的新 WorkManager 提供程序来停用 AndroidManifest.xml
中的默认 WorkManagerInitializer(2.6以后用
InitializationProvider)
引入:
现在,默认 WorkManager 初始化程序已停用,您可以使用按需初始化。为此,android.app.Application
类必须提供 androidx.work.Configuration.Provider
的实现。
class MyApplication() : Application(), Configuration.Provider {override fun getWorkManagerConfiguration() =Configuration.Builder().setMinimumLoggingLevel(android.util.Log.DEBUG).build()
}Java:public Configuration getWorkManagerConfiguration() {Configuration.Builder builder= new Configuration.Builder();builder.setMinimumLoggingLevel(android.util.Log.DEBUG);return builder.build();}
定义自定义 WorkManager 配置后,WorkManager 会在您调用 WorkManager.getInstance(Context) 时进行初始化,而不是在应用启动时自动初始化
启用 DEBUG 日志记录后,系统会开始显示更多包含日志标记前缀 WM-
的日志
在应用的调试 build 中,您可以使用以下命令从 WorkManager 2.4.0 及更高版本请求诊断信息:
adb shell am broadcast -a "androidx.work.diagnostics.REQUEST_DIAGNOSTICS" -p ""
这提供了以下方面的信息:
诊断信息如下所示(输出通过 logcat
显示)