前言
由于笔者目前水平限制,表达能力有限,尽请见谅。
WorkManager 是 Android Jetpack 库的一部分,提供了一种向后兼容的方式来安排可延迟的异步任务,这些任务即使在应用退出或设备重启后也应该继续执行。它是 Android 推荐的解决方案,用于处理需要保证执行的后台任务。WorkManager 适合用于那些不需要立即执行的任务,但最终需要完成的任务。
上文主要深入了WorkManagerInitializer和WorkContinuation类,接下来将继续深入。
正文
Constraints.kt
这个类用于定义工作执行的约束条件。约束条件可以包括设备的充电状态、网络连接状态、电池状态等。在创建一个 WorkRequest
时,可以通过 Constraints.Builder
来设置这些约束。
我们以设置内容 URI 触发器的任务(仅 API 24+)为例
对于应用开发可以如下设置:
// 监听设备上某个内容提供者的变化
val contentUri = Uri.parse("content://path")
val constraints = Constraints.Builder()
.addContentUriTrigger(contentUri, true) // true表示是否包含子路径的变化
.build()
val workRequest = OneTimeWorkRequest.Builder(MyWork::class.java)
.setConstraints(constraints)
.build()
WorkManager.getInstance(context).enqueue(workRequest)
如下是涉及到的源码
@RequiresApi(24)
fun addContentUriTrigger(uri: Uri, triggerForDescendants: Boolean): Builder {
contentUriTriggers.add(ContentUriTrigger(uri, triggerForDescendants))
return this
}
其中contentUriTriggers定义为val contentUriTriggers: Set<ContentUriTrigger>是一个集合,方便去重
ContentUriTirgger的构造函数如下
equals
使得ContentUriTrigger
实例可以与其他实例进行比较。它首先检查两个对象是否为同一个实例,然后检查它们是否为相同类型,最后比较它们的 uri
和 isTriggeredForDescendants
值。
保证即使两个 ContentUriTrigger
实例在内存中的位置不同,只要它们观察的 Uri
和对后代触发的设置相同,它们就被视为相等。
hashCode
方法提供了一个基于 ContentUriTrigger
实例的 uri
和 isTriggeredForDescendants
值的哈希码。
class ContentUriTrigger(val uri: Uri, val isTriggeredForDescendants: Boolean) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as ContentUriTrigger
if (uri != other.uri) return false
if (isTriggeredForDescendants != other.isTriggeredForDescendants) return false
return true
}
override fun hashCode(): Int {
var result = uri.hashCode()
result = 31 * result + isTriggeredForDescendants.hashCode()
return result
}
}
对于Constraints.Builder类的build方法,源码如下
值得注意的是,方法会检查当前 Android 设备的 API 级别。如果设备运行的是 Android API 级别 24 或更高,它会使用之前通过构建器方法添加的 contentUriTriggers
、triggerContentUpdateDelay
和 triggerMaxContentDelay
值。对于更低的 API 级别,它会将 contentUriTriggers
设置为空集合,并将延迟时间设置为 -1,应该是为了兼容。
fun build(): Constraints {
val contentUriTriggers: Set<ContentUriTrigger>
val triggerContentUpdateDelay: Long
val triggerMaxContentDelay: Long
if (Build.VERSION.SDK_INT >= 24) {
contentUriTriggers = this.contentUriTriggers.toSet()
triggerContentUpdateDelay = this.triggerContentUpdateDelay
triggerMaxContentDelay = triggerContentMaxDelay
} else {
contentUriTriggers = emptySet()
triggerContentUpdateDelay = -1
triggerMaxContentDelay = -1
}
@Suppress("NewApi")
return Constraints(
requiredNetworkRequestCompat = requiredNetworkRequest,
requiredNetworkType = requiredNetworkType,
requiresCharging = requiresCharging,
requiresDeviceIdle = Build.VERSION.SDK_INT >= 23 && requiresDeviceIdle,
requiresBatteryNotLow = requiresBatteryNotLow,
requiresStorageNotLow = requiresStorageNotLow,
contentTriggerMaxDelayMillis = triggerMaxContentDelay,
contentTriggerUpdateDelayMillis = triggerContentUpdateDelay,
contentUriTriggers = contentUriTriggers,
)
}
设置其他Constraints约束,流程以及源码结构与如上没有太多异处,暂时不再过多研究。
本文内容感觉有些简短,不过先这样吧。