Android NDK开发详解后台任务之CoroutineWorker 中的线程处理
对于 Kotlin 用户,WorkManager 为协程提供了一流的支持。如要开始使用,请将 work-runtime-ktx 包含到您的 gradle 文件中。不要扩展 Worker,而应扩展 CoroutineWorker,后者包含 doWork() 的挂起版本。例如,如果要构建简单的 CoroutineWorker 来执行某些网络操作,您需要执行以下操作:
class CoroutineDownloadWorker(
context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
val data = downloadSynchronously("https://www.google.com")
saveData(data)
return Result.success()
}
}
请注意,CoroutineWorker.doWork() 是一个“挂起”函数。此代码不同于 Worker,不会在 Configuration 中指定的 Executor 中运行,而是默认为 Dispatchers.Default。您可以提供自己的 CoroutineContext 来自定义这个行为。在上面的示例中,您可能希望在 Dispatchers.IO 上完成此操作,如下所示:
class CoroutineDownloadWorker(
context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
withContext(Dispatchers.IO) {
val data = downloadSynchronously("https://www.google.com")
saveData(data)
return Result.success()
}
}
}
CoroutineWorker 通过取消协程并传播取消信号来自动处理停工情况。您无需执行任何特殊操作来处理停工情况。
在其他进程中运行 CoroutineWorker
您还可以使用 RemoteCoroutineWorker(ListenableWorker 的实现)将工作器绑定到特定进程。
RemoteCoroutineWorker 会使用您在构建工作请求时于输入数据中提供的两个额外参数绑定到特定进程:ARGUMENT_CLASS_NAME 和 ARGUMENT_PACKAGE_NAME。
以下示例演示了如何构建绑定到特定进程的工作请求:
Kotlin
val PACKAGE_NAME = "com.example.background.multiprocess"
val serviceName = RemoteWorkerService::class.java.name
val componentName = ComponentName(PACKAGE_NAME, serviceName)
val data: Data = Data.Builder()
.putString(ARGUMENT_PACKAGE_NAME, componentName.packageName)
.putString(ARGUMENT_CLASS_NAME, componentName.className)
.build()
return OneTimeWorkRequest.Builder(ExampleRemoteCoroutineWorker::class.java)
.setInputData(data)
.build()
Java
String PACKAGE_NAME = "com.example.background.multiprocess";
String serviceName = RemoteWorkerService.class.getName();
ComponentName componentName = new ComponentName(PACKAGE_NAME, serviceName);
Data data = new Data.Builder()
.putString(ARGUMENT_PACKAGE_NAME, componentName.getPackageName())
.putString(ARGUMENT_CLASS_NAME, componentName.getClassName())
.build();
return new OneTimeWorkRequest.Builder(ExampleRemoteCoroutineWorker.class)
.setInputData(data)
.build();
对于每个 RemoteWorkerService,您还需要在 AndroidManifest.xml 文件中添加服务定义:
<manifest ... >
<service
android:name="androidx.work.multiprocess.RemoteWorkerService"
android:exported="false"
android:process=":worker1" />
<service
android:name=".RemoteWorkerService2"
android:exported="false"
android:process=":worker2" />
...
</manifest>
示例
WorkManagerMultiProcessSample