其他
WorkManager 在 Kotlin 中的实践
WorkManager https://developer.android.google.cn/topic/libraries/architecture/workmanager/ Android Jetpack https://developer.android.google.cn/jetpack/
目前为止 WorkManager 系列已经讨论过:
在这篇文章中,我们将讨论:
在 Kotlin 中如何使用 WorkManager
CoroutineWorker 类
如何使用 TestListenableWorkerBuilder 测试您的 CoroutineWorker 类
CoroutineWorker https://developer.android.google.cn/reference/kotlin/androidx/work/CoroutineWorker TestListenableWorkerBuilder https://developer.android.google.cn/reference/androidx/work/testing/TestListenableWorkerBuilder
Kotlin 版的 WorkManager
KTX 库 https://developer.android.google.cn/kotlin/ktx 发布日志 https://developer.android.google.cn/jetpack/androidx/releases/work
更简洁且惯用
Data myData = new Data.Builder()
.putInt(KEY_ONE_INT, aInt)
.putIntArray(KEY_ONE_INT_ARRAY, aIntArray)
.putString(KEY_ONE_STRING, aString)
.build();
inline fun workDataOf(vararg pairs: Pair<String, Any?>): Data
workDataOf https://developer.android.google.cn/reference/kotlin/androidx/work/package-summary#workdataof
val data = workDataOf(
KEY_MY_INT to myIntVar,
KEY_MY_INT_ARRAY to myIntArray,
KEY_MY_STRING to myString
)
CoroutineWorker
Worker https://developer.android.google.cn/reference/androidx/work/Worker.html ListenableWorker https://developer.android.google.cn/reference/androidx/work/ListenableWorker RxWorker https://developer.android.google.cn/reference/androidx/work/RxWorker.html Kotlin 协程
https://kotlinlang.org/docs/reference/coroutines-overview.html
CoroutineWorker
https://developer.android.google.cn/reference/kotlin/androidx/work/CoroutineWorker.html
在 WorkManager 中进行线程处理 https://developer.android.google.cn/topic/libraries/architecture/workmanager/advanced/threading
class MyWork(context: Context, params: WorkerParameters) :
CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
return try {
// 做点什么
Result.success()
} catch (error: Throwable) {
Result.failure()
}
}
}
CoroutineWorker#doWork() https://developer.android.google.cn/reference/kotlin/androidx/work/CoroutineWorker.html#dowork
与 Worker 不同,此代码不会在 WorkManager 的 Configuration 中指定的 Executor 上运行。
class MyWork(context: Context, params: WorkerParameters) :
CoroutineWorker(context, params) {
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
return try {
// 做点什么
Result.success()
} catch (error: Throwable) {
Result.failure()
}
}
}
很少需要改变 CoroutineWorker 使用的 Dispatcher,因为 Dispatchers.Default 可以满足大多数情况下的需求。
codelab https://codelabs.developers.google.com/codelabs/android-workmanager-kt/
测试 Worker 类
WorkManager 测试文档页面 https://developer.android.google.cn/topic/libraries/architecture/workmanager/how-to/testing 使用 WorkManager 2.1.0 进行测试 https://developer.android.google.cn/topic/libraries/architecture/workmanager/how-to/testing-210 WorkManagerTestInitHelper#getTestDriver() https://developer.android.google.cn/reference/kotlin/androidx/work/testing/WorkManagerTestInitHelper#gettestdriver
@RunWith(JUnit4::class)
class MyWorkTest {
private lateinit var context: Context
@Before
fun setup() {
context = ApplicationProvider.getApplicationContext()
}
@Test
fun testMyWork() {
// 获取 ListenableWorker 的实例
val worker =
TestListenableWorkerBuilder<MyWork>(context).build()
// 同步的运行 worker
val result = worker.startWork().get()
assertThat(result, `is`(Result.success()))
}
}
class MyWork(context: Context, params: WorkerParameters) :
CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
val serverUrl = inputData.getString("SERVER_URL")
return try {
// 通过 URL 做点什么
Result.success()
} catch (error: TitleRefreshError) {
if (runAttemptCount <3) {
Result.retry()
} else {
Result.failure()
}
}
}
}
@Test
fun testMyWorkRetry() {
val data = workDataOf("SERVER_URL" to "[http://fake.url](http://fake.url)")
// 获取 ListenableWorker,并将 RunAttemptCount 设置为 2
val worker = TestListenableWorkerBuilder<MyWork>(context)
.setInputData(data)
.setRunAttemptCount(2)
.build()
// 启动同步执行的任务
val result = worker.startWork().get()
assertThat(result, `is`(Result.retry()))
}
@Test
fun testMyWorkFailure() {
val data = workDataOf("SERVER_URL" to "[http://fake.url](http://fake.url)")
// 获取 ListenableWorker,并将 RunAttemptCount 设置为 3
val worker = TestListenableWorkerBuilder<MyWork>(context)
.setInputData(data)
.setRunAttemptCount(3)
.build()
// 启动同步执行的任务
val result = worker.startWork().get()
assertThat(result, `is`(Result.failure()))
}
总结
WorkManager 相关资源
开发者指南 | 在 WorkManager 中进行线程处理 https://developer.android.google.cn/topic/libraries/architecture/workmanager/ 参考指南 | androidx.work https://developer.android.google.cn/reference/androidx/work/package-summary Codelab | 使用 WorkManager 处理后台任务 https://codelabs.developers.google.com/codelabs/android-workmanager WorkManager 的公开问题追踪器 https://issuetracker.google.com/issues?q=componentid:409906 发行日志 | WorkManager https://developer.android.google.cn/jetpack/androidx/releases/work Stack Overflow 的 [android-workmanager] 标签 https://stackoverflow.com/questions/tagged/android-workmanager WorkManager 的源码 (AOSP的一部分) https://android.googlesource.com/platform/frameworks/support/+/master/work
推荐阅读