Cập nhật tác vụ đã được thêm vào hàng đợi

WorkManager cho phép bạn cập nhật WorkRequest sau khi đã đưa nó vào hàng đợi. Điều này thường cần thiết trong những ứng dụng lớn hơn, thường xuyên thay đổi các quy tắc ràng buộc hoặc cần cập nhật trình thực thi nhanh chóng. Kể từ WorkManager phiên bản 2.8.0, API updateWork() sẽ là phương tiện để thực hiện việc này.

Phương thức updateWork() cho phép bạn thay đổi một số khía cạnh nhất định của WorkRequest một cách nhanh chóng mà không phải thực hiện quy trình huỷ và thêm một chế độ mới theo cách thủ công. Việc này giúp đơn giản hoá đáng kể quá trình phát triển.

Tránh huỷ công việc

Thường thì bạn không nên huỷ một WorkRequest hiện có và thêm một WorkRequest mới. Làm như vậy có thể khiến ứng dụng lặp lại một số tác vụ và có thể yêu cầu bạn viết một lượng đáng kể mã bổ sung.

Hãy xem các ví dụ sau đây về trường hợp huỷ WorkRequest có thể gây ra khó khăn:

  • Yêu cầu phụ trợ: Nếu bạn huỷ một Worker trong khi đang tính toán tải trọng để gửi đến máy chủ, thì Worker mới cần phải bắt đầu lại và tính toán lại tải trọng có thể gây tốn kém.
  • Lên lịch: Nếu huỷ PeriodicWorkRequest và muốn PeriodicWorkRequest mới thực thi trên cùng lịch biểu, thì bạn cần tính toán mức chênh lệch thời gian để đảm bảo thời gian thực thi mới phù hợp với yêu cầu công việc trước đó.

API updateWork() cho phép bạn cập nhật các quy tắc ràng buộc của yêu cầu công việc và các tham số khác mà không gặp vấn đề gì khi huỷ và thêm một yêu cầu mới vào hàng đợi.

Thời điểm huỷ công việc

Có những trường hợp bạn nên trực tiếp huỷ WorkRequest thay vì gọi updateWork(). Đây là những việc bạn nên làm khi muốn thay đổi tính chất cơ bản của tác vụ mà bạn đã đưa vào hàng đợi.

Thời điểm cập nhật công việc

Hãy tưởng tượng một ứng dụng ảnh thực hiện việc sao lưu ảnh của người dùng hằng ngày. Thiết bị đã thêm PeriodicWorkRequest vào hàng đợi để thực hiện việc này. WorkRequest có các hạn chế yêu cầu thiết bị phải sạc và kết nối với Wi-Fi.

Tuy nhiên, người dùng chỉ sạc thiết bị của họ trong 20 phút mỗi ngày bằng bộ sạc nhanh. Trong trường hợp này, ứng dụng nên cập nhật WorkRequest để nới lỏng giới hạn sạc, nhờ đó ứng dụng vẫn có thể tải ảnh lên ngay cả khi thiết bị chưa được sạc đầy.

Trong trường hợp này, bạn có thể sử dụng phương thức updateWork() để cập nhật các quy tắc ràng buộc của yêu cầu công việc.

Cách cập nhật công việc

Phương thức updateWork() cung cấp một phương thức đơn giản để cập nhật WorkRequest hiện có mà không cần huỷ và thêm một phương thức mới vào hàng đợi.

Để sử dụng tác vụ cập nhật trong hàng đợi, hãy làm theo các bước sau:

  1. Lấy mã nhận dạng hiện có cho công việc trong hàng đợi: Lấy mã nhận dạng của WorkRequest mà bạn muốn cập nhật. Bạn có thể truy xuất mã nhận dạng này bằng bất kỳ API getWorkInfo nào hoặc bằng cách duy trì mã đó theo cách thủ công từ WorkRequest ban đầu để truy xuất sau này bằng thuộc tính công khai WorkRequest.id trước khi thêm vào hàng đợi.
  2. Tạo WorkRequest mới: Tạo một WorkRequest mới và sử dụng WorkRequest.Builder.setID() để đặt mã nhận dạng cho khớp với mã của WorkRequest hiện có.
  3. Đặt điều kiện ràng buộc: Sử dụng WorkRequest.Builder.setConstraints() để truyền các quy tắc ràng buộc mới cho WorkManager.
  4. Gọi updateWork: Truyền WorkRequest mới đến updateWork().

Ví dụ về cập nhật công việc

Dưới đây là một đoạn mã mẫu trong Kotlin minh hoạ cách sử dụng phương thức updateWork() để thay đổi các giới hạn pin của WorkRequest dùng để tải ảnh lên:

suspend fun updatePhotoUploadWork() {
    // Get instance of WorkManager.
    val workManager = WorkManager.getInstance(context)

    // Retrieve the work request ID. In this example, the work being updated is unique
    // work so we can retrieve the ID using the unique work name.
    val photoUploadWorkInfoList = workManager.getWorkInfosForUniqueWork(
        PHOTO_UPLOAD_WORK_NAME
    ).await()

    val existingWorkRequestId = photoUploadWorkInfoList.firstOrNull()?.id ?: return

    // Update the constraints of the WorkRequest to not require a charging device.
    val newConstraints = Constraints.Builder()
        // Add other constraints as required here.
        .setRequiresCharging(false)
        .build()

    // Create new WorkRequest from existing Worker, new constraints, and the id of the old WorkRequest.
    val updatedWorkRequest: WorkRequest =
        OneTimeWorkRequestBuilder<MyWorker>()
            .setConstraints(newConstraints)
            .setId(existingWorkRequestId)
            .build()

    // Pass the new WorkRequest to updateWork().
    workManager.updateWork(updatedWorkRequest)
}

Xử lý kết quả

updateWork() trả về một ListenableFuture<UpdateResult>. UpdateResult đã cho có thể có một trong vài giá trị nêu rõ việc WorkManager có thể áp dụng các thay đổi của bạn hay không. Cột này cũng cho biết thời điểm có thể áp dụng thay đổi.

Để biết thêm thông tin, hãy xem updateWork() UpdateResult tài liệu tham khảo.

Theo dõi công việc bằng nhiều thế hệ

Mỗi lần bạn cập nhật một WorkRequest, quá trình tạo sẽ tăng thêm 1. Việc này cho phép bạn theo dõi chính xác WorkRequest hiện đang được đưa vào hàng đợi. Thế hệ cung cấp cho bạn nhiều quyền kiểm soát hơn khi quan sát, theo dõi và kiểm thử các yêu cầu công việc.

Để tạo WorkRequest, hãy làm theo các bước sau:

  1. WorkInfo: Gọi WorkManager.getWorkInfoById() để truy xuất một thực thể của WorkInfo tương ứng với WorkRequest của bạn.
  2. getGeneration: Gọi getGeneration() trên thực thể của WorkInfo. Int được trả về tương ứng với quá trình tạo WorkRequest.
    • Lưu ý rằng không có trường hoặc thuộc tính tạo, chỉ có phương thức WorkInfo.getGeneration().

Ví dụ về cách tạo kênh

Sau đây là ví dụ về cách triển khai quy trình công việc được mô tả ở trên để truy xuất quá trình tạo WorkRequest.

// Get instance of WorkManager.
val workManager = WorkManager.getInstance(context)

// Retrieve WorkInfo instance.
val workInfo = workManager.getWorkInfoById(oldWorkRequestId)

// Call getGeneration to retrieve the generation.
val generation = workInfo.getGeneration()

Chính sách cập nhật công việc

Trước đây, giải pháp đề xuất để cập nhật công việc định kỳ là thêm PeriodicWorkRequest vào hàng đợi theo chính sách ExistingPeriodicWorkPolicy.REPLACE. Nếu có một PeriodicWorkRequest đang chờ xử lý có cùng id duy nhất, thì yêu cầu công việc mới sẽ huỷ và xoá yêu cầu đó. Chính sách này hiện không được dùng nữa và được thay thế bằng quy trình sử dụng ExistingPeriodicWorkPolicy.UPDATE.

Ví dụ: khi sử dụng enqueueUniquePeriodicWork với PeriodicWorkRequest, bạn có thể khởi chạy PeriodicWorkRequest mới bằng chính sách ExistingPeriodicWorkPolicy.UPDATE. Nếu có một PeriodicWorkRequest đang chờ xử lý có cùng tên duy nhất, WorkManager sẽ cập nhật thành quy cách mới. Theo quy trình công việc này, bạn không cần sử dụng updateWork().