WorkManager
提供了任务调度功能,我们可以对工作进行标记或命名。
1. 入门示例
gradle 引入依赖
将以下依赖项添加到应用模块的 build.gradle 文件中
dependencies {
def work_version = "2.5.0"
// (Java only)
implementation "androidx.work:work-runtime:$work_version"
// Kotlin + coroutines
implementation "androidx.work:work-runtime-ktx:$work_version"
// optional - RxJava2 support
implementation "androidx.work:work-rxjava2:$work_version"
// optional - GCMNetworkManager support
implementation "androidx.work:work-gcm:$work_version"
// optional - Test helpers
androidTestImplementation "androidx.work:work-testing:$work_version"
// optional - Multiprocess support
implementation "androidx.work:work-multiprocess:$work_version"
}
添加依赖项并同步 Gradle 后,下一步要定义一些工作。
2. 定义工作
这里的工作为方便测试进行了简化。实际项目中请改为具体的业务代码。 新建 UploadWorker
类继承 Worker
类。需要 2 个参数 context: Context, params: WorkerParameters
。 在doWork()
方法中是我们的具体任务,在 WorkManager
提供的后台线程上异步运行。
class UploadWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
override fun doWork(): Result {
for (i in 1..3) {
Log.d(TAG, "模拟执行任务 ${tags.first()} ${Thread.currentThread()}")
Thread.sleep(100) // 模拟耗时
}
return Result.success()
}
}
doWork()
方法中我们打印当前线程信息。后面看看线程运行情况。
任务执行完毕,doWork()
需要返回一个 Result
:
Result.success()
:工作成功完成Result.failure()
:工作失败Result.retry()
:工作失败,应根据其重试政策在其他时间尝试
3. 创建 WorkRequest
前面我们定义好了工作类 UploadWorker
。WorkManager
可以调度工作,让工作运行起来。工作可以在某个时间段内定期运行,也可以只运行一次。 要运行工作,涉及到 WorkRequest
类和它的子类。
这里我们演示只运行1次的工作,使用 OneTimeWorkRequest
。 创建 workA
,作为一个Activity 里的变量。
private val mWorkA = OneTimeWorkRequest.Builder(UploadWorker::class.java)
.addTag("workA").build()
创建 workB
val workB = OneTimeWorkRequest.Builder(UploadWorker::class.java)
.addTag("workB").build()
4. 将 WorkRequest 提交给 WorkManager
使用 enqueue
方法将 WorkRequest 提交给 WorkManager。
获取 WorkManager
的实例用 WorkManager.getInstance(applicationContext)
方法。
mWorkA
是变量
WorkManager.getInstance(applicationContext).enqueue(mWorkA)
// ...
workB
是每次都新建一个对象,然后交给 WorkManager
去执行。
val workB = OneTimeWorkRequest.Builder(UploadWorker::class.java)
.addTag("workB").build()
WorkManager.getInstance(applicationContext).enqueue(workB)
执行工作器的确切时间取决于 WorkRequest
中使用的约束和系统优化方式。 Google 官方设计过 WorkManager
,能够在满足约束的情况下提供最佳行为。
5. 运行测试
按钮A触发 mWorkA
,按钮 B 触发 workB
。分别点击按钮A/B
模拟执行任务 workA Thread[pool-2-thread-3,5,main]
模拟执行任务 workA Thread[pool-2-thread-3,5,main]
模拟执行任务 workA Thread[pool-2-thread-3,5,main]
点击按钮B Thread[main,5,main]
模拟执行任务 workB Thread[pool-2-thread-1,5,main]
模拟执行任务 workB Thread[pool-2-thread-1,5,main]
模拟执行任务 workB Thread[pool-2-thread-1,5,main]
观察 log 发现,工作的 doWork()
方法在 WorkManager
提供的后台线程上异步运行。 主线程是 [main,5,main]
,工作的线程是 [pool-2-thread-3,5,main]
。
而在实际操作中发现,多次点击按钮 A,mWorkA
只会执行第一次。后面再点击按钮 A,mWorkA
也不会执行了。