بعد تحديد
Worker
و
WorkRequest
،
تتمثل الخطوة الأخيرة في إضافة عملك إلى قائمة الانتظار. إنّ أبسط طريقة لإدراج العمل في قائمة الانتظار هي
استدعاء طريقة enqueue()
WorkManager، مع تمرير 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. على عكس العلامات، يتم ربط الأسماء الفريدة بمثيل واحد فقط من العمل.
يمكن تطبيق العمل الفريد على كل من العمل لمرة واحدة والعمل الدوري. يمكنك إنشاء تسلسل عمل فريد عن طريق استدعاء إحدى هذه الطرق، اعتمادًا على ما إذا كنت تجدول عملاً متكررًا أو عملاً لمرة واحدة.
WorkManager.enqueueUniqueWork()
للعمل لمرة واحدةWorkManager.enqueueUniquePeriodicWork()
للعمل الدوري
تقبل كلتا الطريقتين 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 بالإجراء الذي يجب اتخاذه عند وجود تعارض. يمكنك القيام بذلك عن طريق تمرير تعداد عند وضع العمل في قائمة الانتظار.
بالنسبة إلى العمل لمرة واحدة، عليك تقديم السمة ExistingWorkPolicy
التي توفّر 4 خيارات للتعامل مع التعارض.
REPLACE
العمل الحالي مع العمل الجديد. يؤدي هذا الخيار إلى إلغاء العمل الحالي.KEEP
العمل الحالي وتجاهل العمل الجديد.APPEND
العمل الجديد حتى نهاية العمل الحالي. ستؤدي هذه السياسة إلى ربط عملك الجديد بالعمل الحالي وتشغيله بعد انتهاء العمل الحالي.
يصبح العمل الحالي شرطًا أساسيًا للعمل الجديد. إذا أصبح العمل الحالي CANCELLED
أو FAILED
، سيكون العمل الجديد أيضًا CANCELLED
أو FAILED
.
إذا كنت تريد تنفيذ العمل الجديد بغض النظر عن حالة العمل الحالي،
استخدِم السمة APPEND_OR_REPLACE
بدلاً من ذلك.
- تعمل
APPEND_OR_REPLACE
بشكل مشابه لـAPPEND
، باستثناء أنها لا تعتمد على حالة العمل مطلوبة. وإذا كان العمل الحالي هوCANCELLED
أوFAILED
، سيستمر العمل الجديد.
بالنسبة إلى العمل خلال الدورة الشهرية، يمكنك تقديم سمة ExistingPeriodicWorkPolicy
التي توفّر خيارَين، هما REPLACE
وKEEP
. تعمل هذه الخيارات بالطريقة نفسها
التي تعمل بها نظيراتها في CurrentWorkPolicy.
ملاحظة عملك
في أي وقت بعد إضافة العمل إلى قائمة الانتظار، يمكنك التحقّق من حالته من خلال طلب بحث
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(); } });
استعلامات العمل المعقدة
يتيح الإصدار 2.4.0 من WorkManager والإصدارات الأحدث تنفيذ طلبات بحث معقدة للمهام المدرَجة في قائمة الانتظار باستخدام عناصر
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);
يتم AND
إضافة كل مكوّن (علامة أو حالة أو اسم) في WorkQuery
مع العناصر الأخرى. كل قيمة في المكوِّن هي 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 دقائق. تمت جدولة العمل لإعادة المحاولة في وقت لاحق.
في ظل هذه الظروف، يتوقف العامل.
يجب أن تلغي بشكل تعاوني أي عمل قمت به قيد التقدم وتطلق أي موارد يحتفظ بها العامل لديك. على سبيل المثال، يجب عليك إغلاق الأسماء المعرِّفة المفتوحة لقواعد البيانات والملفات في هذه المرحلة. هناك آليتان تحت تصرفك لمعرفة متى يتوقف العامل لديك.
معاودة الاتصال onStopped()
يستدعي WorkManager
ListenableWorker.onStopped()
فور توقف عاملك. تجاوز هذه الطريقة لإغلاق أي
موارد قد تحتفظ بها.
سمة isStopped()
يمكنك استدعاء طريقة
ListenableWorker.isStopped()
لمعرفة ما إذا كان قد تم إيقاف عاملك. إذا كنت تجري عمليات طويلة الأمد أو متكررة في عاملك، يجب عليك التحقق من هذه الخاصية بشكل متكرر واستخدامها كإشارة لإيقاف العمل في أسرع وقت ممكن.
ملاحظة: يتجاهل WorkManager
Result
الذي ضبطه العامل
الذي تلقّى إشارة onStop، لأنّ "العامل" سبق أن تم اعتباره
متوقفًا.