Đối với người dùng Kotlin, WorkManager cung cấp dịch vụ hỗ trợ hàng đầu cho coroutine. Để bắt đầu, hãy đưa work-runtime-ktx
vào tệp gradle của bạn. Thay vì mở rộng Worker
, bạn nên mở rộng CoroutineWorker
, vì lớp này có phiên bản tạm ngưng của doWork()
. Ví dụ, nếu muốn tạo một CoroutineWorker
đơn giản để thực hiện một số thao tác mạng, bạn cần làm như sau:
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()
}
}
Xin lưu ý rằng CoroutineWorker.doWork()
là môt hàm tạm ngưng. Không như Worker
, mã này không chạy trên Executor
được chỉ định trong Configuration
của bạn. Thay vào đó, mặc định của mã này là Dispatchers.Default
. Bạn có thể tuỳ chỉnh mã này bằng cách cung cấp CoroutineContext
riêng của mình. Trong ví dụ trên, bạn có thể sẽ muốn thực hiện công việc này trên Dispatchers.IO
như thế này:
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
tự động xử lý các trường hợp công việc bị dừng bằng cách huỷ coroutine và truyền đi các tín hiệu huỷ. Bạn không cần phải làm điều gì đặc biệt để xử lý các trường hợp công việc bị dừng.
Chạy CoroutineWorker trong một quy trình xử lý khác
Bạn cũng có thể liên kết worker với một quy trình cụ thể bằng cách sử dụng một cách triển khai ListenableWorker
là RemoteCoroutineWorker
.
RemoteCoroutineWorker
liên kết với một quy trình cụ thể bằng 2 đối số bổ sung ARGUMENT_CLASS_NAME
và ARGUMENT_PACKAGE_NAME
mà bạn cung cấp dưới dạng một phần của dữ liệu đầu vào khi tạo yêu cầu công việc.
Ví dụ sau đây minh hoạ việc xây dựng một yêu cầu công việc ràng buộc với một quy trình cụ thể:
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();
Đối với mỗi RemoteWorkerService
, bạn cũng cần thêm định nghĩa dịch vụ vào tệp 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>