WorkManager es una biblioteca de extensión de Android Jetpack que le permite planificar fácilmente tareas que pueden posponerse y ser asincrónicas pero deben ejecutarse de manera confiable. Para la mayoría de las tareas en segundo plano, el uso de WorkManager es actualmente la mejor práctica en la plataforma Android.
WorkManager
https://developer.android.google.cn/topic/libraries/architecture/workmanager/
Jetpack de Android
https://developer.android.google.cn/jetpack/
Hasta ahora se ha discutido la serie WorkManager:
En este artículo, discutiremos:
Cómo utilizar WorkManager en Kotlin
CoroutineWorker 类
Cómo utilizar TestListenableWorkerBuilder para probar su clase CoroutineWorker
CoroutineWorker
https://developer.android.google.cn/reference/kotlin/androidx/work/CoroutineWorker
TestListenableWorkerBuilder
https://developer.android.google.cn/reference/androidx/work/testing/TestListenableWorkerBuilder
Versión Kotlin de WorkManager
El código de muestra de este artículo está escrito en Kotlin y usa la biblioteca KTX (Extensiones de Kotlin). La versión KTX de WorkManager proporciona funciones de extensión de Kotlin más concisas e idiomáticas. Como se describe en el registro de versiones de WorkManager, solo necesita agregar la dependencia androidx.work:work-runtime-ktx al archivo build.gradle para usar la versión KTX de WorkManager. Este componente contiene CoroutineWorker y otros métodos de extensión de WorkManager útiles.
Biblioteca KTX
https://developer.android.google.cn/kotlin/ktx
Publicar registro
https://developer.android.google.cn/jetpack/androidx/releases/work
Más conciso e idiomático
Cuando necesita construir un objeto de datos y necesita pasarlo o regresar de la clase Worker, la versión KTX de WorkManager proporciona una especie de azúcar sintáctico. En este caso, el código implementado en la sintaxis de Java es el siguiente:
Data myData = new Data.Builder()
.putInt(KEY_ONE_INT, aInt)
.putIntArray(KEY_ONE_INT_ARRAY, aIntArray)
.putString(KEY_ONE_STRING, aString)
.build();
En Kotlin, podemos usar la función auxiliar workDataOf para escribir el código de forma más concisa:
inline fun workDataOf(vararg pairs: Pair<String, Any?>): Data
workDataOf
https://developer.android.google.cn/reference/kotlin/androidx/work/package-summary#workdataof
Por lo tanto, la expresión Java anterior se puede reescribir como:
val data = workDataOf(
KEY_MY_INT to myIntVar,
KEY_MY_INT_ARRAY to myIntArray,
KEY_MY_STRING to myString
)
CoroutineWorker
Además de las clases Worker (Worker, ListenableWorker y RxWorker) que se pueden implementar en Java, existe la única clase Work que se puede implementar usando Kotlin coroutines-CoroutineWorker.
Trabajador
https://developer.android.google.cn/reference/androidx/work/Worker.html
Trabajador escuchable
https://developer.android.google.cn/reference/androidx/work/ListenableWorker
RxWorker
https://developer.android.google.cn/reference/androidx/work/RxWorker.html
Corutina de Kotlin
https://kotlinlang.org/docs/reference/coroutines-overview.html
CoroutineWorker
https://developer.android.google.cn/reference/kotlin/androidx/work/CoroutineWorker.html
La principal diferencia entre la clase Worker y la clase CoroutineWorker es: El método doWork () de la clase CoroutineWorker es una función de suspensión que puede realizar tareas asincrónicas, mientras que el método doWork () de la clase Worker solo puede realizar tareas síncronas. Otra característica de CoroutineWorker es que puede manejar automáticamente la suspensión y cancelación de tareas, y la clase Worker necesita implementar el método onStopped () para manejar estas situaciones.
Para obtener información de contexto completa, consulte la documentación oficial para subprocesos en WorkManager. Aquí, quiero centrarme en lo que es CoroutineWorker y cubrir algunas diferencias pequeñas pero importantes, así como una comprensión profunda de cómo usar las nuevas funciones de prueba introducidas en WorkManager v2.1 para probar su clase CoroutineWorker.
Procesamiento de subprocesos en WorkManager
https://developer.android.google.cn/topic/libraries/architecture/workmanager/advanced/threading
Como se escribió anteriormente, CoroutineWorker # doWork () es solo una función de suspensión. Se inicia en Dispatchers. De forma predeterminada:
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
Debe recordarse que esta es la diferencia fundamental al usar CoroutineWorker en lugar de Worker o ListenableWorker:
A diferencia de Worker, este código no se ejecutará en el Ejecutor especificado en la Configuración del WorkManager.
Como se acaba de decir, CoroutineWorker # doWork () se inicia en Dispatchers.De forma predeterminada. Puede usar withContext () para personalizar esta configuración.
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()
}
}
}
Rara vez es necesario cambiar el Dispatcher utilizado por CoroutineWorker, porque Dispatchers.Default puede satisfacer las necesidades de la mayoría de situaciones.
Para aprender a usar WorkManager en Kotlin, puede probar este codelab.
codelab
https://codelabs.developers.google.com/codelabs/android-workmanager-kt/
Prueba la clase Worker
WorkManager tiene varias clases de herramientas adicionales que pueden probar fácilmente su trabajo. Puede obtener más información sobre esto en la página de documentación de prueba de WorkManager y la nueva guía para realizar pruebas con WorkManager 2.1.0. La implementación original de la herramienta de prueba hace posible personalizar el WorkManager, de modo que podamos hacerlo aparecer como una ejecución sincrónica, y luego podemos usar WorkManagerTestInitHelper # getTestDriver () para simular retrasos y probar tareas periódicas.
Página de documentación de prueba de WorkManager
https://developer.android.google.cn/topic/libraries/architecture/workmanager/how-to/testing
Utilice WorkManager 2.1.0 para realizar pruebas
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
Se agrega una nueva clase de herramienta en WorkManager v2.1: TestListenableWorkerBuilder, que presenta una nueva forma de probar la clase Worker.
Esta es una actualización muy importante para la clase CoroutineWorker, porque puede ejecutar la clase Worker directamente a través de TestListenableWorkerBuilder para probar si su lógica es correcta.
@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()))
}
}
El punto aquí es que puede obtener el resultado de ejecución de CoroutineWorker sincrónicamente, y luego puede verificar directamente si el comportamiento lógico de la clase Worker es correcto.
Utilice TestListenableWorkerBuilder para pasar datos de entrada a Worker o configure runAttemptCount, que es muy útil para probar la lógica de reintento dentro de Worker.
Por ejemplo, si desea cargar algunos datos en el servidor, puede agregar alguna lógica de reintento teniendo en cuenta los posibles problemas de conexión:
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()
}
}
}
}
Luego, puede usar TestListenableWorkerBuilder en la prueba para probar si la lógica de reintento es correcta:
@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()))
}
para resumir
Con el lanzamiento de WorkManager v2.1 y las nuevas funciones en workManager-testing, CoroutineWorker brilla por su simplicidad y facilidad de uso. Ahora puede probar la clase Worker muy fácilmente, y la experiencia general de usar WorkManager en Kotlin también es muy buena.
Si no ha utilizado CoroutineWorker y otras extensiones incluidas en workmanager-runtime-ktx en su proyecto, se recomienda encarecidamente que las utilice en su proyecto. Al desarrollar con Kotlin (que se ha convertido en mi rutina diaria), esta es mi forma preferida de usar WorkManager.
Espero que este artículo sea útil para usted. Puede dejar un mensaje en el área de comentarios para compartir sus ideas o preguntas sobre el uso de WorkManager.
Recursos relacionados con WorkManager
Guía para desarrolladores | Subprocesos en WorkManager
https://developer.android.google.cn/topic/libraries/architecture/workmanager/
Guía de referencia | androidx.work
https://developer.android.google.cn/reference/androidx/work/package-summary
Codelab | Use WorkManager para manejar tareas en segundo plano
https://codelabs.developers.google.com/codelabs/android-workmanager
Rastreador de problemas públicos de WorkManager
https://issuetracker.google.com/issues?q=componentid:409906
Registro de versiones | WorkManager
https://developer.android.google.cn/jetpack/androidx/releases/work
Etiqueta [Android-workmanager] de Stack Overflow
https://stackoverflow.com/questions/tagged/android-workmanager
Código fuente de WorkManager (parte de AOSP)
https://android.googlesource.com/platform/frameworks/support/+/master/work
Lectura recomendada
Haga clic en la pantalla al final | leer leer el artículo original | Ver documentos chinos oficiales de Android - Usar tareas programadas de WorkManager