Sau khi bạn xác định
Worker
và
WorkRequest
,
bước sau cùng là thêm công việc vào hàng đợi. Cách đơn giản nhất để thêm công việc vào hàng đợi
là gọi phương thức enqueue()
trong WorkManager và chuyển WorkRequest
mà bạn
muốn thực hiện.
Kotlin
val myWork: WorkRequest = // ... OneTime or PeriodicWork WorkManager.getInstance(requireContext()).enqueue(myWork)
Java
WorkRequest myWork = // ... OneTime or PeriodicWork WorkManager.getInstance(requireContext()).enqueue(myWork);
Hãy thận trọng khi thêm công việc vào hàng đợi để tránh trùng lặp. Ví dụ: một ứng dụng có thể cố gắng tải nhật ký của nó lên dịch vụ phụ trợ sau mỗi 24 giờ. Nếu không cẩn thận, bạn có thể thêm nhiều lần một tác vụ vào hàng đợi, mặc dù tác vụ đó chỉ cần chạy một lần. Để đạt được mục tiêu này, bạn có thể lên lịch công việc dưới dạng công việc duy nhất.
Công việc duy nhất
Công việc duy nhất là một khái niệm rõ ràng, giúp đảm bảo bạn chỉ có một phiên bản công việc với tên gọi cụ thể tại một thời điểm. Khác với mã nhận dạng, tên riêng là để mọi người đọc được và do nhà phát triển chỉ định thay vì do WorkManager tạo tự động. Khác với thẻ, tên riêng chỉ liên kết với một phiên bản của công việc.
Bạn có thể áp dụng công việc duy nhất cho cả công việc một lần và công việc định kỳ. Bạn có thể tạo trình tự công việc duy nhất bằng cách gọi một trong các phương thức sau đây, tuỳ theo việc bạn đang lên lịch công việc lặp lại hay công việc một lần.
WorkManager.enqueueUniqueWork()
đối với công việc một lầnWorkManager.enqueueUniquePeriodicWork()
đối với công việc định kỳ
Cả hai phương thức này đều chấp nhận 3 đối số:
- uniqueWorkName –
String
dùng để xác định từng yêu cầu công việc. - existingWorkPolicy –
enum
cho WorkManager biết việc cần làm nếu hiện có chuỗi công việc chưa hoàn thành với tên riêng đó. Xem chính sách xử lý xung đột để biết thêm thông tin. - work –
WorkRequest
để lên lịch.
Bằng cách sử dụng công việc duy nhất, chúng tôi có thể khắc phục sự cố lên lịch trùng lặp được nêu ở phần trước.
Kotlin
val sendLogsWorkRequest = PeriodicWorkRequestBuilderS<endLogsWorker(>24, TimeUnit.HOURS) .setConstraints(Constraints.Builder() .setRequiresCharging(true) .build() ) .build() WorkManager.getInstance(this).enqueueUniquePeriodicWork( "sendLogs", ExistingPeriodicWorkPolicy.KEEP, sendLogsWorkRequest )
Java
PeriodicWorkRequest sendLogsWorkRequest = new PeriodicWorkRequest.Builder(SendLogsWorker.class, 24, TimeUnit.HOURS) .setConstraints(new Constraints.Builder() .setRequiresCharging(true) .build() ) .build(); WorkManager.getInstance(this).enqueueUniquePeriodicWork( "sendLogs", ExistingPeriodicWorkPolicy.KEEP, sendLogsWorkRequest);
Hiện tại, nếu mã chạy khi có công việc sendLogs trong hàng đợi, hệ thống sẽ giữ lại công việc hiện tại và không thêm công việc mới vào.
Trình tự công việc duy nhất cũng có thể giúp ích nếu bạn cần xây dựng dần chuỗi tác vụ dài. Ví dụ: một ứng dụng chỉnh sửa ảnh có thể cho phép người dùng huỷ một chuỗi thao tác dài. Sẽ mất một chút thời gian để thực hiện từng thao tác huỷ, nhưng phải tiến hành theo đúng thứ tự. Trong trường hợp này, ứng dụng có thể tạo một chuỗi "huỷ" và thêm từng thao tác huỷ vào đầu chuỗi đó (nếu cần). Xem phần Chuỗi công việc để biết thêm thông tin chi tiết.
Chính sách xử lý xung đột
Khi lên lịch cho công việc duy nhất, bạn phải cho WorkManager biết hành động cần làm khi xảy ra xung đột. Bạn thực hiện việc này bằng cách truyền một enum khi thêm công việc vào hàng đợi.
Đối với công việc làm một lần, bạn phải cung cấp ExistingWorkPolicy
để hỗ trợ 4 lựa chọn xử lý xung đột.
REPLACE
công việc hiện tại bằng công việc mới. Lựa chọn này sẽ hủy công việc hiện tại.KEEP
công việc hiện tại và bỏ qua công việc mới.APPEND
công việc mới vào cuối công việc hiện tại. Chính sách này sẽ giúp công việc mới liên kết với công việc hiện tại và chạy sau khi công việc hiện tại hoàn thành.
Công việc hiện tại trở thành điều kiện tiên quyết cho công việc mới. Nếu công việc hiện tại
bị CANCELLED
hoặc FAILED
, công việc mới cũng sẽ bị CANCELLED
hoặc FAILED
.
Thay vào đó, nếu bạn muốn thực hiện công việc mới bất kể trạng thái của công việc hiện tại,
hãy dùng APPEND_OR_REPLACE
.
APPEND_OR_REPLACE
có chức năng tương tự nhưAPPEND
, ngoại trừ việc chức năng này không phụ thuộc vào trạng thái công việc tiên quyết. Nếu công việc hiện tại làCANCELLED
hoặcFAILED
, công việc mới vẫn chạy.
Đối với công việc định kỳ, bạn cung cấp
ExistingPeriodicWorkPolicy
để hỗ trợ 2 lựa chọn: REPLACE
và KEEP
. Những lựa chọn này có chức năng giống với
các lựa chọn tương ứng trong ExistingWorkPolicy.
Quan sát công việc
Bất kỳ lúc nào sau khi thêm công việc vào hàng đợi, bạn có thể kiểm tra trạng thái công việc bằng cách truy vấn WorkManager theo name
, id
hoặc theo tag
gắn với công việc đó.
Kotlin
// by id workManager.getWorkInfoById(syncWorker.id) // ListenableFutureW<orkInfo<>/span> // by name workManager.getWorkInfosForUniqueWork("sync") // ListenableFutureL<istW<orkInfo<>/span> > // by tag workManager.getWorkInfosByTag("syncTag") // ListenableFutureL<istW<orkInfo<>/span> >
Java
// by id workManager.getWorkInfoById(syncWorker.id); // ListenableFutureW<orkInfo<>/span> // by name workManager.getWorkInfosForUniqueWork("sync"); // ListenableFutureL<istW<orkInfo<>/span> > // by tag workManager.getWorkInfosByTag("syncTag"); // ListenableFutureL<istW<orkInfo<>/span> >
Truy vấn trả về
ListenableFuture
của đối tượng WorkInfo
, bao gồm
id
công việc, thẻ,
State
hiện tại và bất kỳ tập dữ liệu đầu ra nào
qua
Result.success(outputData)
.
Biến thể LiveData
của từng phương thức cho phép bạn quan sát các thay đổi đối với WorkInfo
bằng cách đăng ký trình nghe. Ví dụ: Nếu muốn hiển thị thông báo cho người dùng khi hoàn thành xong một số công việc, bạn có thể thiết lập như sau:
Kotlin
workManager.getWorkInfoByIdLiveData(syncWorker.id) .observe(viewLifecycleOwner) { workInfo - > if(workInfo?.state == WorkInfo.State.SUCCEEDED) { Snackbar.make(requireView(), R.string.work_completed, Snackbar.LENGTH_SHORT) .show() } }
Java
workManager.getWorkInfoByIdLiveData(syncWorker.id) .observe(getViewLifecycleOwner(), workInfo - >{ if (workInfo.getState() != null && workInfo.getState() == WorkInfo.State.SUCCEEDED) { Snackbar.make(requireView(), R.string.work_completed, Snackbar.LENGTH_SHORT) .show(); } });
Truy vấn công việc phức tạp
WorkManager 2.4.0 trở lên hỗ trợ truy vấn phức tạp cho các công việc trong hàng đợi bằng cách sử dụng đối tượng của
WorkQuery
. WorkQuery hỗ trợ
hoạt động truy vấn công việc bằng cách kết hợp (các) thẻ, trạng thái và tên riêng của công việc đó.
Ví dụ sau hướng dẫn bạn cách tìm tất cả công việc bằng thẻ “syncTag”,
ở trạng thái FAILED
hoặc CANCELLED
và có tên riêng của công việc là
“preProcess” hoặc “sync”.
Kotlin
val workQuery = WorkQuery.Builder .fromTags(listOf("syncTag")) .addStates(listOf(WorkInfo.State.FAILED, WorkInfo.State.CANCELLED)) .addUniqueWorkNames(listOf("preProcess", "sync") ) .build() val workInfos: ListenableFutureL<istW<orkInfo >>= workManager.getWorkInfos(workQuery)
Java
WorkQuery workQuery = WorkQuery.Builder .fromTags(Arrays.asList("syncTag")) .addStates(Arrays.asList(WorkInfo.State.FAILED, WorkInfo.State.CANCELLED)) .addUniqueWorkNames(Arrays.asList("preProcess", "sync") ) .build(); ListenableFutureL<istW<orkInfo >>workInfos = workManager.getWorkInfos(workQuery);
Mỗi thành phần (thẻ, trạng thái hoặc tên) trong WorkQuery
là AND
-ed với các thành phần khác. Từng giá trị trong thành phần đều là OR
-ed. Ví dụ: (name1 OR name2
OR ...) AND (tag1 OR tag2 OR ...) AND (state1 OR state2 OR ...)
.
WorkQuery
cũng hoạt động với mã tương đương trong LiveData là
getWorkInfosLiveData()
.
Huỷ và dừng công việc
Nếu không cần thực hiện công việc đã thêm vào hàng đợi trước đó, bạn có thể yêu cầu
huỷ. Hệ thống có thể huỷ công việc theo name
, id
hoặc theo tag
gắn với công việc đó.
Kotlin
// by id workManager.cancelWorkById(syncWorker.id) // by name workManager.cancelUniqueWork("sync") // by tag workManager.cancelAllWorkByTag("syncTag")
Java
// by id workManager.cancelWorkById(syncWorker.id); // by name workManager.cancelUniqueWork("sync"); // by tag workManager.cancelAllWorkByTag("syncTag");
WorkManager nâng cao sẽ bí mật kiểm tra
State
công việc. Nếu công việc
đã hoàn tất,
thì sẽ không có điều gì xảy ra. Nếu không, trạng thái công việc sẽ đổi thành
CANCELLED
và không thể
thực hiện công việc trong tương lai. Mọi công việc
WorkRequest
phụ thuộc
vào công việc này cũng
sẽ bị CANCELLED
.
Hiện tại, công việc RUNNING
sẽ nhận được lệnh gọi đến
ListenableWorker.onStopped()
.
Ghi đè phương thức này để xử lý mọi tình huống xoá có thể xảy ra. Xem phần dừng
Worker đang chạy để biết thêm thông tin.
Dừng Worker đang chạy
Sau đây là một vài lý do khác nhau khiến WorkManager dừng Worker
đang chạy của bạn:
- Bạn yêu cầu huỷ công việc một cách rõ ràng (ví dụ: bằng cách gọi
WorkManager.cancelWorkById(UUID)
). - Trong trường hợp là công việc duy nhất,
bạn rõ ràng đã thêm
WorkRequest
mới vào hàng đợi bằngExistingWorkPolicy
củaREPLACE
. Ngay lập tức,WorkRequest
cũ sẽ bị coi là huỷ. - Các quy tắc ràng buộc của công việc không được đáp ứng nữa.
- Hệ thống đã hướng dẫn ứng dụng của bạn dừng công việc vì một số lý do. Trường hợp này có thể xảy ra nếu bạn trễ hạn thực thi 10 phút. Công việc này sẽ được lên lịch để thực hiện lại sau.
Trong những tình huống này, Worker sẽ dừng lại.
Bạn nên phối hợp huỷ mọi công việc đang tiến hành và giải phóng tài nguyên mà Worker đang nắm giữ. Ví dụ: Vào thời điểm này, bạn nên đóng các quy trình xử lý đang mở đối với cơ sở dữ liệu và tệp. Có 2 cơ chế bạn có thể áp dụng để biết được khi nào Worker dừng lại.
Gọi lại onStopped()
WorkManager gọi
ListenableWorker.onStopped()
ngay khi Worker dừng lại. Hãy ghi đè phương thức này để đóng
mọi tài nguyên bạn có thể đang nắm giữ.
Thuộc tính isStopped()
Bạn có thể gọi phương thức
ListenableWorker.isStopped()
để kiểm tra xem worker đã dừng hay chưa. Nếu đang
thực hiện các thao tác lâu dài hoặc lặp đi lặp lại trong Worker, bạn nên
kiểm tra thuộc tính này thường xuyên và dùng thuộc tính này làm tín hiệu để dừng công việc càng sớm
càng tốt.
Lưu ý: WorkManager bỏ qua
Result
do Worker đặt
đã nhận được tín hiệu onStop, vì Worker này bị coi là đã
dừng hoạt động.