Android WorkManager 工作约束,延迟与查询工作

本贴最后更新于 949 天前,其中的信息可能已经斗转星移

WorkManager 工作约束,延迟与查询工作

本文可能会混用“工作”与“任务”这两个词。
本文例子使用 Kotlin

准备一个工作类(任务)UploadWorker2

class UploadWorker2(context: Context, params: WorkerParameters) : Worker(context, params) {
    override fun doWork(): Result {
        Log.d(TAG, "模拟执行任务2 ${Thread.currentThread()}")
        return Result.success()
    }
}

工作约束

约束可让工作延迟到满足最佳条件时运行。下面的约束适用于 WorkManager

名称 说明
NetworkType 约束运行工作所需的网络类型。例如 Wi-Fi (UNMETERED)。
BatteryNotLow 若为 true,那么当设备处于“电量不足模式”时,工作不会运行。
RequiresCharging 若为 true,那么工作只能在设备充电时运行。
DeviceIdle 若为 true,则设备必须处于空闲状态才能运行工作。如果考虑到其他应用的性能,建议用这个约束。
StorageNotLow 若为 true,那么当设备上的存储空间不足时,工作不会运行。

可用 Constraints.Builder() 来创建工作约束。然后将 Constraints 实例分配给 WorkRequest.Builder()
也就是说,工作约束是针对工作 WorkRequest 的。

下面这个工作约束,只有 1 个要求,在设备使用计费流量是执行任务。

val constraints = Constraints.Builder()
        .setRequiredNetworkType(NetworkType.METERED)
        .build()
val d1 = OneTimeWorkRequest.Builder(UploadWorker2::class.java)
        .setConstraints(constraints)
        .addTag("约束").build()
mIdList.add(d1.id) // 登记任务id,可去掉
WorkManager.getInstance(applicationContext).enqueue(d1)

真机测试中,如果一开始手机用着 wifi,那么任务不会执行。而关掉 wifi,打开流量开关,就会执行任务。
这就是满足最佳条件时运行。

NetworkType 说明

androidx.work.NetworkType 是一个枚举类。目前有

枚举 说明
NOT_REQUIRED 这个工作不需要网络
CONNECTED 这个工作需要有网络连接
UNMETERED 需要 Wi-Fi
NOT_ROAMING 非漫游网络
METERED 需要按流量计费的网络

延迟工作

如果工作没有约束,或者当工作加入队列时所有约束都得到了满足,那么系统可能会选择立即运行该工作。
如果不希望工作立即运行,可以给工作设定一个延迟时间。

下面这个工作是要延迟 3 秒钟。

val d1 = OneTimeWorkRequest.Builder(UploadWorker2::class.java)
        .addTag("延迟1")
        .setInitialDelay(3, TimeUnit.SECONDS)
        .build()
WorkManager.getInstance(applicationContext).enqueue(d1)

enqueue 任务后,查一下任务状态。工作从 ENQUEUED 状态,执行完毕后变成了 SUCCEEDED

WorkInfo{mId='2794b4dd-7c02-4fd0-9851-8798a0da3bb2', mState=ENQUEUED, mOutputData=Data {}, mTags=[com.rustfisher.tutorial2020.workmanaer.WorkManagerAct$UploadWorker2, 延迟1], mProgress=Data {}}

WorkInfo{mId='2794b4dd-7c02-4fd0-9851-8798a0da3bb2', mState=SUCCEEDED, mOutputData=Data {}, mTags=[com.rustfisher.tutorial2020.workmanaer.WorkManagerAct$UploadWorker2, 延迟1], mProgress=Data {}}

查询工作

使用 UUID 查询

新建工作的时候,系统会分配一个 UUID。我们可以记录 UUID 到 mIdList 里。通过 UUID 可以查询到工作当前的状态。

val mgr = WorkManager.getInstance(applicationContext)
for (id in mIdList) {
    val cur = mgr.getWorkInfoById(id)
    Log.d(TAG, "查询任务 ${cur.get()}")
}

一个工作状态的例子,状态是 ENQUEUED

WorkInfo{mId='16cc292d-f140-488f-9ab5-a0d22b95d128', mState=ENQUEUED, mOutputData=Data {}, mTags=[com.rustfisher.tutorial2020.workmanaer.WorkManagerAct$UploadWorker, r1], mProgress=Data {}}

使用 tag 查询

前面我们给工作打上 tag。可以用 WorkManagergetWorkInfosByTag() 方法把指定 tag 的工作查出来。

val mgr = WorkManager.getInstance(applicationContext)

for (w in mgr.getWorkInfosByTag("约束1").get()) {
    Log.d(TAG, "$w")
}

工作状态的例子,下面这个工作 UploadWorker 状态是 SUCCEEDED,tag 里有 约束1

WorkInfo{mId='fed1974c-77e5-46ba-8b38-f6c01d68fe4c', mState=SUCCEEDED, mOutputData=Data {}, mTags=[com.rustfisher.tutorial2020.workmanaer.WorkManagerAct$UploadWorker, 约束1], mProgress=Data {}}

需要注意的是,工作的状态是存储起来的。即使重启 app 或者手机,都可以查到这个工作的状态。
假设查询 tag 是 约束1,我们能得到之前创建的含有这个 约束1 标签的工作。

参考

  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    331 引用 • 315 回帖 • 82 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...