إدارة العمل

بعد تحديد 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، فريدة وترتبط الأسماء بمثيل واحد من العمل فقط.

يمكن تطبيق العمل الفريد على كل من العمل لمرة واحدة والعمل الدوري. يمكنك إنشاء تسلسل عمل فريد عن طريق استدعاء إحدى هذه الطرق، اعتمادًا على ما إذا كان تقوم بجدولة عمل متكرر أو عمل لمرة واحدة.

تقبل كلتا الطريقتين 3 وسيطات:

  • uniqueWorkName - عنصر String يُستخدم لتعريف العمل بشكل فريد طلبك.
  • existingWorkPolicy - enum الذي يخبر WorkManager بما يجب تنفيذه إذا كانت هناك سلسلة عمل غير مكتملة بهذا الاسم الفريد. عرض يمكنك الاطّلاع على سياسة حلّ التعارضات للحصول على مزيد من المعلومات.
  • work - WorkRequest لتحديد موعد.

باستخدام عمل فريد، يمكننا حل مشكلة الجدولة المكررة المذكورة سابقًا.

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);

الآن، إذا تم تشغيل التعليمة البرمجية أثناء وجود مهمة SendLogs في قائمة الانتظار بالفعل، الاحتفاظ بالمهمة ولا تتم إضافة وظيفة جديدة.

يمكن أن تكون تسلسلات العمل الفريدة مفيدة أيضًا إذا كنت بحاجة إلى إنشاء وسلسلة طويلة من المهام. على سبيل المثال، قد يسمح أحد تطبيقات تعديل الصور للمستخدمين بالتراجع عن وسلسلة طويلة من الإجراءات. قد تستغرق كل عملية من عمليات التراجع هذه بعض الوقت، ولكن فيجب تنفيذها بالترتيب الصحيح. في هذه الحالة، يمكن للتطبيق إنشاء "تراجع" وإلحاق كل عملية التراجع بالسلسلة حسب الحاجة. الاطّلاع على سلسلة الأعمال لمزيد من التفاصيل.

سياسة حلّ النزاعات

عند جدولة عمل فريد، يجب إخبار WorkManager بالإجراء الذي يجب اتخاذه وجود تعارض. يمكنك القيام بذلك عن طريق إدخال تعداد عند إدراج العمل في قائمة الانتظار.

بالنسبة للعمل لمرة واحدة، فإنك تقدم ExistingWorkPolicy، يتيح 4 خيارات للتعامل مع التعارض.

  • REPLACE عنصر حالي للعمل مع العمل الجديد. يؤدي هذا الخيار إلى إلغاء العمل الحالي.
  • KEEP من الأعمال الحالية العمل الجديد وتجاهله.
  • APPEND العمل الجديد نهاية العمل الحالي. ستؤدي هذه السياسة إلى chained إلى العمل الحالي، الذي يعمل بعد انتهاء العمل الحالي.

يصبح العمل الحالي شرطًا أساسيًا للعمل الجديد. إذا كان العمل الحالي يصبح CANCELLED أو FAILED، يصبح العمل الجديد أيضًا CANCELLED أو FAILED. إذا كنت تريد أن يعمل العمل الجديد بغض النظر عن حالة العمل الحالي، استخدِم APPEND_OR_REPLACE بدلاً من ذلك.

  • APPEND_OR_REPLACE تشبه الدالة APPEND، باستثناء أنها لا تعتمد على حالة العمل المتطلبات الأساسية. إذا كان العمل الحالي هو CANCELLED أو FAILED، لا يزال العمل الجديد قيد التنفيذ.

بالنسبة للعمل عبر فترة الحيض، فإنك تقدم ExistingPeriodicWorkPolicy، والذي يتيح خيارَين، REPLACE وKEEP تعمل هذه الخيارات بنفس كنظيرين لها في ExistingWorkPolicy.

مراقبة عملك

في أي وقت بعد وضع العمل في قائمة الانتظار، يمكنك التحقق من حالته عن طريق الاستعلام WorkManager بواسطة name أو id أو tag مرتبط به.

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>
>

يقوم الاستعلام بإرجاع 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: 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);

يتم تحديد كل مكوّن (علامة أو حالة أو اسم) في 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() ويمكنك تجاهُل هذه الطريقة للتعامل مع أي عملية إزالة محتملة. عرض إيقاف عامل تشغيل لمزيد من المعلومات.

إيقاف عامل قيد التشغيل

هناك بضعة أسباب مختلفة قد تؤدي إلى إيقاف "Worker" من قِبل WorkManager:

  • لقد طلبت صراحةً إلغاءها (من خلال الاتصال WorkManager.cancelWorkById(UUID)، على سبيل المثال).
  • في حالة العمل الفريد، لقد أضفت WorkRequest جديدة في قائمة الانتظار بشكل صريح مع ExistingWorkPolicy من REPLACE يُعتبر WorkRequest القديم ملغاًا على الفور.
  • لم تعد قيود عملك تمت تلبيتها.
  • أصدر النظام تعليمات إلى تطبيقك بإيقاف عملك لسبب ما. يمكن أن يحدث إذا تجاوزت الموعد النهائي للتنفيذ وهو 10 دقائق. العمل مجدول لإعادة المحاولة في وقت لاحق.

في هذه الحالات، يتم إيقاف العامل الخاص بك.

يجب العمل بشكل تعاوني على إلغاء أي عمل كنت قيد التقدم والإفراج عن أي عمل والموارد التي يحتفظ بها العامل. على سبيل المثال، يجب عليك إغلاق فتح بقواعد البيانات والملفات في هذه المرحلة. هناك آليتين في تصرفك لفهم متى يتوقف العامل.

استدعاء onStopped()

استدعاء WorkManager ListenableWorker.onStopped() ما إن يتم إيقافه. يمكنك تجاوز هذه الطريقة لإغلاق وأي موارد قد تحتفظ بها.

خاصية isStopped()

يمكنك الاتصال ListenableWorker.isStopped() لمعرفة ما إذا كان قد سبق أن تم إيقاف العمل إذا كنت إجراء عمليات طويلة الأمد أو متكررة في العامل، فيجب عليك تحقَّق من هذا الموقع كثيرًا واستخدِمه كإشارة لتوقُّف العمل في أقرب وقت قدر الإمكان.

ملاحظة: يتجاهل WorkManager الرمز Result الذي حدّده عامل تلقى إشارة onStop، لأن العامل يُعد تَوَقَّفْنَا.