เมื่อคุณกำหนด
Worker
และ
WorkRequest
ของคุณ
ขั้นตอนสุดท้ายคือการจัดคิวงาน วิธีที่ง่ายที่สุดในการจัดคิวงาน
คือการเรียกใช้เมธอด WorkManager enqueue()
โดยส่งผ่าน WorkRequest
ที่คุณ
ที่ต้องการวิ่ง
Kotlin
val myWork: WorkRequest = // ... OneTime or PeriodicWork WorkManager.getInstance(requireContext()).enqueue(myWork)
Java
WorkRequest myWork = // ... OneTime or PeriodicWork WorkManager.getInstance(requireContext()).enqueue(myWork);
โปรดใช้ความระมัดระวังในการจัดคิวงานเพื่อหลีกเลี่ยงการซ้ำซ้อน ตัวอย่างเช่น แอปอาจพยายามอัปโหลด บันทึกไปยังบริการแบ็กเอนด์ทุกๆ 24 ชั่วโมง หากไม่ระวัง คุณอาจ ต้องเข้าคิวงานเดิมหลายครั้ง แม้ว่างานนั้นจะต้อง เรียกใช้ครั้งเดียว หากต้องการบรรลุเป้าหมายนี้ คุณสามารถตั้งเวลางานให้เป็นงานที่ไม่ซ้ำได้
ผลงานที่ไม่ซ้ำใคร
ผลงานที่ไม่ซ้ำใครคือแนวคิดที่มีประสิทธิภาพที่รับประกันว่าคุณจะได้รับเพียงผลงานเดียว ของการทำงานร่วมกันกับชื่อหนึ่งๆ ต่อครั้ง ชื่อที่ไม่ซ้ำกันแตกต่างจากรหัสตรง เป็นเนื้อหาที่มนุษย์อ่านได้และระบุโดยนักพัฒนาซอฟต์แวร์แทนที่จะสร้างขึ้นโดยอัตโนมัติ โดย WorkManager เลิกชอบ tags ไม่ซ้ำกัน จะเชื่อมโยงกับงานเพียงครั้งเดียว
งานที่ไม่ซ้ำใครใช้ได้กับทั้งงานแบบครั้งเดียวและงานตามช่วงระยะเวลา คุณสามารถสร้าง ลำดับงานที่ไม่ซ้ำกันโดยเรียกใช้หนึ่งในวิธีเหล่านี้ โดยขึ้นอยู่กับว่า คุณต้องกำหนดเวลาทำงานซ้ำหรืองานแบบครั้งเดียว
WorkManager.enqueueUniqueWork()
สำหรับงานแบบครั้งเดียวWorkManager.enqueueUniquePeriodicWork()
สำหรับงานที่มีระยะเวลา
ทั้ง 2 วิธีนี้ยอมรับอาร์กิวเมนต์ 3 แบบ
- uniqueWorkName -
String
ที่ใช้เพื่อระบุผลงานโดยไม่ซ้ำกัน อีกครั้ง - existingWorkPolicy -
enum
ที่บอก WorkManager ว่าต้องทำอะไรบ้าง มีห่วงโซ่งานที่ยังไม่เสร็จ ซึ่งมีชื่อไม่ซ้ำนั้นอยู่แล้ว โปรดดู นโยบายการระงับข้อพิพาทสำหรับข้อมูลเพิ่มเติม - work -
WorkRequest
ที่จะกำหนดเวลา
ด้วยการใช้การทำงานเฉพาะ เราสามารถแก้ไขปัญหาการตั้งเวลาซ้ำที่เรากล่าวไว้ก่อนหน้านี้
Kotlin
val sendLogsWorkRequest = PeriodicWorkRequestBuilder<SendLogsWorker>(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);
ทีนี้ หากโค้ดทำงานในขณะที่งาน sendLogs อยู่ในคิว รหัสที่มีอยู่ งานจะถูกเก็บไว้และจะไม่เพิ่มงานใหม่
ลำดับการทำงานที่เฉพาะเจาะจงยังมีประโยชน์ในกรณีที่คุณต้องค่อยๆ สร้าง งานที่ยาวนาน เช่น แอปแก้ไขรูปภาพอาจให้ผู้ใช้เลิกทำ ห่วงโซ่การดำเนินการที่ยาว การดำเนินการเลิกทำแต่ละครั้งอาจใช้เวลาสักครู่ แต่ ตามลำดับที่ถูกต้อง ในกรณีนี้ แอปอาจ สร้างการ "เลิกทำ" ห่วงโซ่ แล้วเพิ่มการดำเนินการเลิกทำแต่ละรายการต่อท้ายเชนตามที่จำเป็น ดูงานเชน เพื่อดูรายละเอียดเพิ่มเติม
นโยบายการแก้ไขข้อขัดแย้ง
เมื่อกำหนดเวลางานที่ไม่ซ้ำกัน คุณต้องแจ้งให้ WorkManager ทราบว่าต้องดำเนินการใดเมื่อใด ก็เกิดข้อขัดแย้ง ซึ่งทำได้โดยส่ง Enum เมื่อจัดคิวงาน
สำหรับงานแบบครั้งเดียว คุณจะต้องจัดเตรียม
ExistingWorkPolicy
ซึ่ง
สนับสนุน 4 ตัวเลือกสำหรับการจัดการข้อขัดแย้ง
- มี
REPLACE
อยู่แล้ว ที่จะทำงานชิ้นใหม่ ตัวเลือกนี้จะยกเลิกงานที่มีอยู่ KEEP
งานที่มีอยู่และ ไม่ต้องสนใจงานใหม่APPEND
ทำงานใหม่เพื่อ เมื่องานที่มีอยู่สิ้นสุดลง นโยบายนี้จะทำให้งานใหม่ของคุณ ที่ผูกไว้ไว้กับ งานที่มีอยู่ โดยทำงานหลังจากงานที่มีอยู่เสร็จสิ้น
งานที่มีอยู่แล้วจะกลายเป็นข้อกำหนดเบื้องต้นสำหรับงานใหม่ หากงานที่มีอยู่
เปลี่ยนเป็น CANCELLED
หรือ FAILED
งานใหม่จะเป็น CANCELLED
หรือ FAILED
ด้วย
หากคุณต้องการให้งานใหม่ทำงานไม่ว่างานที่มีอยู่จะอยู่ในสถานะอะไร
ใช้ APPEND_OR_REPLACE
แทน
APPEND_OR_REPLACE
ฟังก์ชันที่คล้ายกับAPPEND
เว้นแต่ว่าจะไม่อิงตาม สถานะการทำงานตามเกณฑ์เบื้องต้น หากงานที่มีอยู่คือCANCELLED
หรือ คุณFAILED
งานใหม่จะยังคงทำงานอยู่
สำหรับงานที่ต้องทำประจำ คุณต้องให้
ExistingPeriodicWorkPolicy
ซึ่งรองรับ 2 ตัวเลือก ได้แก่ REPLACE
และ KEEP
ตัวเลือกเหล่านี้ทำงานเหมือนเดิม
เป็นคู่หูที่มีอยู่
สังเกตงานของคุณ
หลังจากจัดคิวงานแล้ว คุณจะตรวจสอบสถานะของงานได้ทุกเมื่อด้วยการค้นหา
WorkManager โดย name
, id
หรือโดย tag
ที่เกี่ยวข้อง
Kotlin
// by id workManager.getWorkInfoById(syncWorker.id) // ListenableFuture<WorkInfo> // by name workManager.getWorkInfosForUniqueWork("sync") // ListenableFuture<List<WorkInfo>> // by tag workManager.getWorkInfosByTag("syncTag") // ListenableFuture<List<WorkInfo>>
Java
// by id workManager.getWorkInfoById(syncWorker.id); // ListenableFuture<WorkInfo> // by name workManager.getWorkInfosForUniqueWork("sync"); // ListenableFuture<List<WorkInfo>> // by tag workManager.getWorkInfosByTag("syncTag"); // ListenableFuture<List<WorkInfo>>
การค้นหาจะแสดงผล
ListenableFuture
ของออบเจ็กต์ WorkInfo
ซึ่งรวมถึง
id
ของผลงาน แท็ก ของงาน
State
ปัจจุบันและข้อมูลเอาต์พุตทั้งหมด
ตั้งค่าผ่าน
Result.success(outputData)
ตัวแปร LiveData
ของแต่ละ
จะช่วยให้คุณสังเกตการเปลี่ยนแปลงWorkInfo
ได้ด้วยการลงทะเบียน
ผู้ฟัง เช่น ถ้าต้องการแสดงข้อความให้กับผู้ใช้เมื่อ
งานบางชิ้นเสร็จเรียบร้อยแล้ว คุณสามารถตั้งค่าได้ดังนี้
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(); } });
การค้นหางานที่ซับซ้อน
WorkManager 2.4.0 ขึ้นไปรองรับการค้นหาที่ซับซ้อนสำหรับงานที่มีการจัดคิวโดยใช้
WorkQuery
ออบเจ็กต์ รองรับ WorkQuery
ค้นหางานโดยใช้ทั้งแท็ก สถานะ และชื่องานที่ไม่ซ้ำกัน
ตัวอย่างต่อไปนี้แสดงวิธีค้นหางานทั้งหมดกับแท็ก “syncTag”
ที่อยู่ในสถานะ FAILED
หรือ CANCELLED
และมีชื่อผลงานที่ไม่ซ้ำกันของ
“preProcess” หรือ “sync”
Kotlin
val workQuery = WorkQuery.Builder .fromTags(listOf("syncTag")) .addStates(listOf(WorkInfo.State.FAILED, WorkInfo.State.CANCELLED)) .addUniqueWorkNames(listOf("preProcess", "sync") ) .build() val workInfos: ListenableFuture<List<WorkInfo>> = 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(); ListenableFuture<List<WorkInfo>> workInfos = workManager.getWorkInfos(workQuery);
คอมโพเนนต์แต่ละรายการ (แท็ก สถานะ หรือชื่อ) ใน WorkQuery
จะมี AND
พร้อมเมธอด
อื่นๆ แต่ละค่าในคอมโพเนนต์คือ OR
-ed เช่น (name1 OR name2
OR ...) AND (tag1 OR tag2 OR ...) AND (state1 OR state2 OR ...)
WorkQuery
ยังใช้ได้กับเวอร์ชันเทียบเท่า LiveData ด้วย
getWorkInfosLiveData()
กำลังยกเลิกและหยุดงาน
หากไม่ต้องการให้งานที่จัดคิวไว้ทำงานก่อนหน้านี้แล้ว คุณสามารถขอให้แสดง
จะถูกยกเลิก งานสามารถยกเลิกได้โดยname
id
หรือtag
ที่เกี่ยวข้อง
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 จะตรวจสอบ
State
ของงาน หากงานคือ
เสร็จสิ้นแล้ว
ไม่มีอะไรเกิดขึ้น มิฉะนั้น สถานะของงานจะเปลี่ยนเป็น
CANCELLED
และงาน
จะไม่ทำงานอีกในอนาคต ช่วง
งาน WorkRequest
ที่อิงตาม
ในงานนี้จะ
และเป็น CANCELLED
ด้วย
งานอยู่ใน RUNNING
ในขณะนี้
รับสายที่
ListenableWorker.onStopped()
ลบล้างวิธีนี้เพื่อจัดการการล้างข้อมูลที่อาจเกิดขึ้น ดูการหยุด
ผู้กำลังทำงานเพื่อดูข้อมูลเพิ่มเติม
หยุดผู้ปฏิบัติงานที่ทำงานอยู่
มีสาเหตุหลายประการที่ทำให้ WorkManager หยุดการทำงานของ Worker
ดังนี้
- คุณขอยกเลิกอย่างชัดแจ้ง (โดยการโทร
WorkManager.cancelWorkById(UUID)
) - ในกรณีที่เป็นผลงานที่ไม่ซ้ำ
คุณได้จัดคิว
WorkRequest
ใหม่อย่างชัดเจนExistingWorkPolicy
จากREPLACE
WorkRequest
เดิมจะถูกยกเลิกทันที - ไม่เป็นไปตามข้อจำกัดของงานอีกต่อไป
- ระบบสั่งให้แอปหยุดงานด้วยเหตุผลบางอย่าง วิธีนี้ หากเกินกำหนดเวลา ของการดำเนินการที่ 10 นาที ผลงาน กำหนดเวลาลองอีกครั้งในภายหลัง
ในกรณีเช่นนี้ ผู้ปฏิบัติงานของคุณจะหยุดทำงาน
คุณควรร่วมมือกันล้มเลิกงานใดๆ ที่กำลังทำอยู่และปลด ทรัพยากรที่ผู้ปฏิบัติงานยึดถืออยู่ ตัวอย่างเช่น คุณควรปิด "เปิด" กับฐานข้อมูลและไฟล์ในจุดนี้ มีกลไก 2 แบบ เพื่อทำความเข้าใจว่าผู้ปฏิบัติงานของคุณกำลังจะหยุดงานเมื่อใด
onStopped() Callback
เรียกใช้ WorkManager
ListenableWorker.onStopped()
ทันทีที่ผู้ปฏิบัติงานหยุดทำงาน ลบล้างเมธอดนี้เพื่อปิด
ทรัพยากรใดๆ ที่คุณครอบครองอยู่
พร็อพเพอร์ตี้ isStopped()
คุณสามารถเรียกใช้
ListenableWorker.isStopped()
เพื่อตรวจสอบว่าผู้ปฏิบัติงานหยุดทำงานแล้วหรือไม่ หากคุณ
การดำเนินการที่ใช้เวลานานหรือซ้ำๆ ใน Worker คุณควร
หมั่นตรวจสอบคุณสมบัตินี้และใช้เป็นสัญญาณให้หยุดทำงานโดยเร็วที่สุด
ให้มากที่สุด
หมายเหตุ: WorkManager จะไม่สนใจฟังก์ชัน
Result
ตั้งค่าโดยผู้ปฏิบัติงาน
ที่ได้รับสัญญาณ onStop เนื่องจากผู้ปฏิบัติงานได้รับการพิจารณาแล้ว
หยุดแล้ว