تناول دليل البدء كيفية إنشاء WorkRequest
وإضافته إلى قائمة الانتظار.
ستتعرّف في هذا الدليل على كيفية تحديد عناصر WorkRequest وتخصيصها
للتعامل مع حالات الاستخدام الشائعة، مثل كيفية:
- جدولة العمل لمرة واحدة والعمل المتكرر
- ضبط قيود العمل، مثل طلب الاتصال بشبكة Wi-Fi أو الشحن
- ضمان الحد الأدنى من التأخير في تنفيذ العمل
- ضبط استراتيجيات إعادة المحاولة والتراجع
- تمرير بيانات الإدخال إلى العمل
- تجميع الأعمال ذات الصلة معًا باستخدام العلامات
نظرة عامة
يتم تحديد العمل في WorkManager باستخدام WorkRequest. لجدولة أي عمل باستخدام WorkManager، عليك أولاً إنشاء عنصر WorkRequest ثم وضعه في قائمة الانتظار.
Kotlin
val myWorkRequest = ...
WorkManager.getInstance(myContext).enqueue(myWorkRequest)
Java
WorkRequest myWorkRequest = ...
WorkManager.getInstance(myContext).enqueue(myWorkRequest);
يحتوي الكائن WorkRequest على جميع المعلومات التي يحتاجها WorkManager
لجدولة عملك وتشغيله. وتتضمّن القيود التي يجب استيفاؤها لتنفيذ عملك، ومعلومات الجدولة مثل التأخيرات أو الفواصل الزمنية المتكررة، وإعدادات إعادة المحاولة، وقد تتضمّن بيانات الإدخال إذا كان عملك يعتمد عليها.
WorkRequest هو صنف أساسي مجرّد. هناك نوعان من عمليات التنفيذ المشتقة من هذه الفئة يمكنك استخدامهما لإنشاء الطلب، وهما OneTimeWorkRequest وPeriodicWorkRequest.
كما تشير أسماؤهما، فإنّ OneTimeWorkRequest مفيد لجدولة
المهام غير المتكررة، بينما PeriodicWorkRequest أكثر ملاءمة
لجدولة المهام التي تتكرر على فترات زمنية معيّنة.
جدولة عمل لمرة واحدة
بالنسبة إلى العمل الأساسي الذي لا يتطلّب أي إعدادات إضافية، استخدِم الطريقة الثابتة from:
Kotlin
val myWorkRequest = OneTimeWorkRequest.from(MyWork::class.java)
Java
WorkRequest myWorkRequest = OneTimeWorkRequest.from(MyWork.class);
بالنسبة إلى المهام الأكثر تعقيدًا، يمكنك استخدام أداة إنشاء:
Kotlin
val uploadWorkRequest: WorkRequest =
OneTimeWorkRequestBuilder<MyWork>()
// Additional configuration
.build()
Java
WorkRequest uploadWorkRequest =
new OneTimeWorkRequest.Builder(MyWork.class)
// Additional configuration
.build();
جدولة المهام المُعجَّلة
قدّم الإصدار 2.7.0 من WorkManager مفهوم المهمة المُعجَّلة. يتيح ذلك لـ WorkManager تنفيذ المهام المهمة مع منح النظام تحكّمًا أفضل في الوصول إلى الموارد.
تتميّز المهام المُعجَّلة بالخصائص التالية:
- الأهمية: تناسب المهام المُعجَّلة المهام المهمة للمستخدم أو التي يبدأها المستخدم.
- السرعة: المهام المُعجَّلة هي الأنسب للمهام القصيرة التي تبدأ على الفور وتكتمل في غضون بضع دقائق.
- الحصص: تحدّد الحصة على مستوى النظام التي تحدّ من وقت التنفيذ في المقدّمة ما إذا كان يمكن بدء مهمة مُعجَّلة.
- إدارة الطاقة: من غير المرجّح أن تؤثر قيود إدارة الطاقة، مثل ميزتَي "توفير شحن البطارية" و"الاستراحة"، في المهام المُعجَّلة.
- وقت الاستجابة: ينفّذ النظام المهمة المُعجَّلة على الفور، بشرط أن يسمح عبء العمل الحالي للنظام بذلك، ما يعني أنّ هذه المهام حساسة لوقت الاستجابة ولا يمكن جدولتها لتنفيذها لاحقًا.
من حالات الاستخدام المحتملة للمهام المُعجَّلة إرسال رسالة أو صورة مرفقة في تطبيق محادثات. وبالمثل، قد يحتاج التطبيق الذي يتعامل مع عملية دفع أو اشتراك إلى استخدام مهمة مُعجَّلة. وذلك لأنّ هذه المهام مهمة للمستخدم، ويتم تنفيذها بسرعة في الخلفية، ويجب أن تبدأ على الفور، ويجب أن يستمر تنفيذها حتى إذا أغلق المستخدم التطبيق.
الحصص
يجب أن يخصّص النظام وقتًا لتنفيذ مهمة مُعجَّلة قبل أن يتمكّن من تشغيلها. وقت التنفيذ ليس غير محدود. بدلاً من ذلك، يحصل كل تطبيق على حصة من وقت التنفيذ. عندما يستخدم تطبيقك وقت التنفيذ ويصل إلى الحصة المخصّصة له، لن تتمكّن من تنفيذ المهام المُعجَّلة إلى أن يتم تحديث الحصة. يسمح ذلك لنظام Android بموازنة الموارد بين التطبيقات بشكل أكثر فعالية.
يعتمد مقدار وقت التنفيذ المتاح للتطبيق على مجموعة الاستعداد وأهمية العملية.
يمكنك تحديد ما يحدث عندما لا تسمح حصة التنفيذ بتشغيل مهمة مُعجَّلة على الفور. اطّلِع على المقتطفات التالية لمعرفة التفاصيل.
تنفيذ المهام المُعجَّلة
اعتبارًا من الإصدار 2.7 من WorkManager، يمكن لتطبيقك استدعاء setExpedited() للإشارة إلى أنّه يجب تشغيل WorkRequest في أسرع وقت ممكن باستخدام مهمة مُعجَّلة. يقدّم مقتطف الرمز التالي مثالاً على كيفية استخدام setExpedited():
Kotlin
val request = OneTimeWorkRequestBuilder<SyncWorker>()
<b>.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)</b>
.build()
WorkManager.getInstance(context)
.enqueue(request)
Java
OneTimeWorkRequest request = new OneTimeWorkRequestBuilder<T>()
.setInputData(inputData)
<b>.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)</b>
.build();
في هذا المثال، ننشئ مثيلاً من OneTimeWorkRequest ونستدعي
setExpedited() عليه. بعد ذلك، يصبح هذا الطلب مهمة مُعجَّلة. إذا كانت الحصة تسمح بذلك، سيبدأ تشغيلها على الفور في الخلفية. إذا تم استخدام الحصة، تشير المَعلمة OutOfQuotaPolicy إلى أنّه يجب تنفيذ الطلب كمهمة عادية غير مُعجَّلة.
التوافق مع الأنظمة القديمة والخدمات التي تعمل في المقدّمة
للحفاظ على التوافق مع الأنظمة القديمة للمهام المُعجَّلة، قد يشغّل WorkManager خدمة تعمل في المقدّمة على إصدارات النظام الأساسي الأقدم من Android 12. ويمكن للخدمات التي تعمل في المقدّمة عرض إشعار للمستخدم.
تتيح الطريقتان getForegroundInfoAsync() وgetForegroundInfo() في Worker
لـ WorkManager عرض إشعار عند استدعاء setExpedited()
قبل الإصدار Android 12.
يجب أن تنفّذ أي فئة ListenableWorker طريقة getForegroundInfo إذا أردت طلب تنفيذ المهمة كمهمة مُعجَّلة.
عند استهداف الإصدار 12 من نظام التشغيل Android أو الإصدارات الأحدث، تظل الخدمات التي تعمل في المقدّمة متاحة لك من خلال طريقة setForeground المقابلة.
عامل
لا يعرف العاملون ما إذا كان العمل الذي يقومون به يتم تسريعه أم لا. ومع ذلك، يمكن لـ
عرض إشعار على بعض إصدارات Android عند تسريع تنفيذ
WorkRequest.
لتفعيل ذلك، توفّر واجهة WorkManager طريقة getForegroundInfoAsync()،
والتي يجب تنفيذها حتى تتمكّن واجهة WorkManager من عرض إشعار لبدء
ForegroundService نيابةً عنك عند الضرورة.
CoroutineWorker
إذا كنت تستخدم CoroutineWorker، عليك تنفيذ getForegroundInfo(). بعد ذلك، يمكنك تمريرها إلى setForeground() في غضون doWork(). سيؤدي ذلك إلى إنشاء الإشعار في إصدارات Android الأقدم من 12.
انظر المثال التالي:
class ExpeditedWorker(appContext: Context, workerParams: WorkerParameters):
CoroutineWorker(appContext, workerParams) {
override suspend fun getForegroundInfo(): ForegroundInfo {
return ForegroundInfo(
NOTIFICATION_ID, createNotification()
)
}
override suspend fun doWork(): Result {
TODO()
}
private fun createNotification() : Notification {
TODO()
}
}
سياسات الحصص
يمكنك التحكّم في ما يحدث للمهام المُعجَّلة عندما يصل تطبيقك إلى
الحصة المخصّصة له من عمليات التنفيذ. للمتابعة، يمكنك تمرير setExpedited():
-
OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST، ما يؤدي إلى تشغيل المهمة كطلب عمل عادي يوضّح المقتطف السابق ذلك. -
OutOfQuotaPolicy.DROP_WORK_REQUEST، ما يؤدي إلى إلغاء الطلب في حال عدم توفّر حصة كافية
المهام المُعجَّلة المؤجَّلة
يحاول النظام تنفيذ مهمة مُعجَّلة معيّنة في أسرع وقت ممكن بعد استدعاء المهمة. ومع ذلك، كما هو الحال مع أنواع المهام الأخرى، قد يؤجّل النظام بدء مهمة مُعجَّلة جديدة، كما في الحالات التالية:
- الحِمل: حِمل النظام مرتفع جدًا، ويمكن أن يحدث ذلك عندما يكون هناك عدد كبير جدًا من المهام قيد التشغيل، أو عندما لا تتوفّر في النظام ذاكرة كافية.
- الحصة: تم تجاوز الحد الأقصى المسموح به لحصة المهام المُعجَّلة. تستخدم المهام المُعجَّلة نظام حصص يستند إلى مجموعات تطبيقات وضع الاستعداد ويحدّ من الحد الأقصى لوقت التنفيذ ضمن نافذة زمنية متجددة. تكون الحصص المستخدَمة للمهام المُعجَّلة أكثر تقييدًا من تلك المستخدَمة لأنواع أخرى من المهام التي يتم تنفيذها في الخلفية.
جدولة العمل الدوري
قد يتطلّب تطبيقك أحيانًا تنفيذ مهام معيّنة بشكل دوري. على سبيل المثال، قد ترغب في الاحتفاظ بنسخة احتياطية من بياناتك بشكل دوري، أو تنزيل محتوى جديد في تطبيقك، أو تحميل السجلات إلى خادم.
في ما يلي كيفية استخدام PeriodicWorkRequest لإنشاء عنصر
WorkRequest يتم تنفيذه بشكل دوري:
Kotlin
val saveRequest =
PeriodicWorkRequestBuilder<SaveImageToFileWorker>(1, TimeUnit.HOURS)
// Additional configuration
.build()
Java
PeriodicWorkRequest saveRequest =
new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class, 1, TimeUnit.HOURS)
// Constraints
.build();
في هذا المثال، تتم جدولة العمل بفاصل زمني مدته ساعة واحدة.
يتم تحديد الفترة الفاصلة على أنّها الحد الأدنى للوقت بين التكرارات. يعتمد الوقت المحدّد لتنفيذ العامل على القيود التي تستخدمها في عنصر WorkRequest وعلى التحسينات التي يجريها النظام.
فواصل زمنية مرنة للتشغيل
إذا كانت طبيعة عملك تجعله حساسًا لتوقيت التشغيل، يمكنك ضبط
PeriodicWorkRequest ليتم تشغيله خلال فترة
مرنة داخل كل فترة زمنية، كما هو موضّح في الشكل 1.

الشكل 1: يعرض المخطّط البياني فترات متكرّرة مع الفترة المرنة التي يمكن تشغيل العمل فيها.
لتحديد عمل دوري بفترة مرنة، يمكنك تمرير flexInterval مع
repeatInterval عند إنشاء PeriodicWorkRequest. تبدأ الفترة المرنة في repeatInterval - flexInterval، وتستمر حتى نهاية الفاصل الزمني.
في ما يلي مثال على عمل دوري يمكن تنفيذه خلال آخر 15 دقيقة من كل فترة مدتها ساعة واحدة.
Kotlin
val myUploadWork = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(
1, TimeUnit.HOURS, // repeatInterval (the period cycle)
15, TimeUnit.MINUTES) // flexInterval
.build()
Java
WorkRequest saveRequest =
new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class,
1, TimeUnit.HOURS,
15, TimeUnit.MINUTES)
.build();
يجب أن تكون الفترة الزمنية للتكرار أكبر من أو تساوي
PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS ويجب أن تكون الفترة الزمنية المرنة أكبر من أو تساوي
PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS`.
تأثير القيود على العمل الدوري
يمكنك تطبيق قيود على العمل الدوري. على سبيل المثال، يمكنك إضافة قيد إلى طلب العمل بحيث لا يتم تنفيذ العمل إلا عندما يكون جهاز المستخدم قيد الشحن. في هذه الحالة، حتى إذا انقضت الفترة الزمنية المحدّدة للتكرار،
لن يتم تشغيل PeriodicWorkRequest إلى أن يتم استيفاء هذا الشرط. قد يؤدي ذلك إلى تأخير تنفيذ عملك، أو حتى تخطّيه إذا لم يتم استيفاء الشروط خلال فترة التنفيذ.
قيود العمل
Constraints تضمن تأجيل العمل إلى أن يتم استيفاء الشروط المثلى. تتوفّر القيود التالية في WorkManager:
| NetworkType | يفرض قيودًا على نوع الشبكة المطلوبة لتنفيذ عملك.
على سبيل المثال، شبكة Wi-Fi (UNMETERED).
|
| BatteryNotLow | عند ضبط هذه السياسة على "صحيح"، لن يتم تنفيذ عملك إذا كان الجهاز في وضع "البطارية منخفضة". |
| RequiresCharging | عند ضبطها على "صحيح"، سيتم تنفيذ عملك فقط عندما يكون الجهاز قيد الشحن. |
| DeviceIdle | عند ضبط هذه السياسة على "صحيح"، يتطلّب ذلك أن يكون جهاز المستخدم غير نشط قبل تشغيل العمل. ويمكن أن يكون ذلك مفيدًا لتشغيل العمليات المجمّعة التي قد يكون لها تأثير سلبي في أداء التطبيقات الأخرى التي تعمل بشكل نشط على جهاز المستخدم. |
| StorageNotLow | عند ضبط هذه السياسة على "صحيح"، لن يتم تنفيذ عملك إذا كانت مساحة التخزين المتوفّرة للمستخدم على الجهاز منخفضة جدًا. |
لإنشاء مجموعة من القيود وربطها ببعض الأعمال، أنشِئ مثيلاً من النوع Constraints باستخدام Constraints.Builder() وعيّنه إلى WorkRequest.Builder().
على سبيل المثال، تنشئ التعليمة البرمجية التالية طلب عمل لا يتم تشغيله إلا عندما يكون جهاز المستخدم قيد الشحن ومتصلاً بشبكة Wi-Fi:
Kotlin
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresCharging(true)
.build()
val myWorkRequest: WorkRequest =
OneTimeWorkRequestBuilder<MyWork>()
.setConstraints(constraints)
.build()
Java
Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresCharging(true)
.build();
WorkRequest myWorkRequest =
new OneTimeWorkRequest.Builder(MyWork.class)
.setConstraints(constraints)
.build();
عند تحديد قيود متعددة، سيتم تشغيل عملك فقط عند استيفاء جميع القيود.
في حال عدم استيفاء أحد القيود أثناء تنفيذ عملك، سيوقف WorkManager العامل. ستتم بعد ذلك إعادة محاولة تنفيذ العمل عند استيفاء جميع القيود.
العمل المتأخر
في حال عدم وجود قيود على عملك أو استيفاء جميع القيود عند إضافة عملك إلى قائمة الانتظار، قد يختار النظام تشغيل العمل على الفور. إذا كنت لا تريد تنفيذ العمل على الفور، يمكنك تحديد بدء العمل بعد حد أدنى من التأخير الأولي.
في ما يلي مثال على كيفية ضبط عملك ليتم تشغيله بعد 10 دقائق على الأقل من وضعه في قائمة الانتظار.
Kotlin
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
.setInitialDelay(10, TimeUnit.MINUTES)
.build()
Java
WorkRequest myWorkRequest =
new OneTimeWorkRequest.Builder(MyWork.class)
.setInitialDelay(10, TimeUnit.MINUTES)
.build();
على الرغم من أنّ المثال يوضّح كيفية ضبط مهلة أولية لـ OneTimeWorkRequest، يمكنك أيضًا ضبط مهلة أولية لـ PeriodicWorkRequest. في هذه الحالة، سيتم تأخير التشغيل الأول فقط
لعملك الدوري.
سياسة إعادة المحاولة والرقود
إذا كنت تريد أن يعيد WorkManager محاولة تنفيذ عملك، يمكنك عرض
Result.retry() من العامل. تتم بعد ذلك إعادة جدولة عملك وفقًا لمهلة التراجع وسياسة التراجع.
يحدّد تأخير التراجع الحد الأدنى من الوقت الذي يجب انتظاره قبل إعادة محاولة تنفيذ عملك بعد المحاولة الأولى. لا يمكن أن تقل هذه القيمة عن 10 ثوانٍ (أو MIN_BACKOFF_MILLIS).
تحدّد سياسة التراجع كيفية زيادة مهلة التراجع بمرور الوقت لمحاولات إعادة المحاولة اللاحقة. تتيح واجهة WorkManager استخدام سياستَين للتراجع، وهما
LINEARوEXPONENTIAL.
لكل طلب عمل سياسة تراجع ومهلة تراجع. السياسة التلقائية
هي EXPONENTIAL مع تأخير لمدة 30 ثانية، ولكن يمكنك إلغاء ذلك في
إعدادات طلب العمل.
في ما يلي مثال على تخصيص مهلة التراجع والسياسة.
Kotlin
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
.setBackoffCriteria(
BackoffPolicy.LINEAR,
WorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS)
.build()
Java
WorkRequest myWorkRequest =
new OneTimeWorkRequest.Builder(MyWork.class)
.setBackoffCriteria(
BackoffPolicy.LINEAR,
WorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS)
.build();
في هذا المثال، تم ضبط الحدّ الأدنى لمهلة التراجع على أدنى قيمة مسموح بها، وهي 10 ثوانٍ. بما أنّ السياسة هي LINEAR، ستزيد الفترة الفاصلة بين محاولات إعادة الإرسال بمقدار 10 ثوانٍ تقريبًا مع كل محاولة جديدة. على سبيل المثال، إذا انتهت المحاولة الأولى بعرض Result.retry()، ستتم إعادة المحاولة بعد 10 ثوانٍ، ثم بعد 20 ثانية، ثم بعد 30 ثانية، ثم بعد 40 ثانية، وهكذا، إذا استمر العمل في عرض Result.retry() بعد المحاولات اللاحقة. إذا تم ضبط سياسة التراجع على EXPONENTIAL، سيكون تسلسل مدة إعادة المحاولة أقرب إلى 20 و40 و80.
الإشارة إلى العمل
يتضمّن كل طلب عمل معرّفًا فريدًا يمكن استخدامه لتحديد هذا العمل لاحقًا من أجل إلغائه أو مراقبة مستوى تقدّمه.
إذا كانت لديك مجموعة من الأعمال ذات الصلة منطقيًا، فقد تجد أنه من المفيد أيضًا وضع علامة على عناصر العمل هذه. تتيح لك ميزة الإشارة إلى المنتجات التعامل مع مجموعة من طلبات العمل معًا.
على سبيل المثال، تلغي الدالة WorkManager.cancelAllWorkByTag(String) جميع طلبات العمل التي تحمل علامة معيّنة، بينما تعرض الدالة WorkManager.getWorkInfosByTag(String) قائمة بعناصر WorkInfo التي يمكن استخدامها لتحديد حالة العمل الحالية.
يوضّح الرمز التالي كيفية إضافة علامة "تنظيف" إلى عملك:
Kotlin
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
.addTag("cleanup")
.build()
Java
WorkRequest myWorkRequest =
new OneTimeWorkRequest.Builder(MyWork.class)
.addTag("cleanup")
.build();
أخيرًا، يمكن إضافة علامات متعددة إلى طلب عمل واحد. يتم تخزين هذه العلامات داخليًا كمجموعة من السلاسل. للحصول على مجموعة العلامات المرتبطة بـ WorkRequest، يمكنك استخدام WorkInfo.getTags().
من فئة Worker، يمكنك استرداد مجموعة العلامات باستخدام
ListenableWorker.getTags().
تحديد بيانات الإدخال
قد يتطلب عملك إدخال بيانات من أجل القيام بعمله. على سبيل المثال، قد يتطلّب العمل الذي يعالج تحميل صورة أن يكون معرّف الموارد المنتظم (URI) للصورة التي سيتم تحميلها كإدخال.
يتم تخزين قيم الإدخال كأزواج مفتاح/قيمة في كائن Data
ويمكن ضبطها في طلب العمل. سترسل واجهة WorkManager الإدخال Data إلى
عملك عند تنفيذه. يمكن لفئة Worker الوصول إلى وسيطات الإدخال من خلال استدعاء Worker.getInputData(). يوضّح الرمز التالي كيفية إنشاء مثيل Worker يتطلّب بيانات إدخال وكيفية إرسالها في طلب العمل.
Kotlin
// Define the Worker requiring input
class UploadWork(appContext: Context, workerParams: WorkerParameters)
: Worker(appContext, workerParams) {
override fun doWork(): Result {
val imageUriInput =
inputData.getString("IMAGE_URI") ?: return Result.failure()
uploadFile(imageUriInput)
return Result.success()
}
...
}
// Create a WorkRequest for your Worker and sending it input
val myUploadWork = OneTimeWorkRequestBuilder<UploadWork>()
.setInputData(workDataOf(
"IMAGE_URI" to "http://..."
))
.build()
Java
// Define the Worker requiring input
public class UploadWork extends Worker {
public UploadWork(Context appContext, WorkerParameters workerParams) {
super(appContext, workerParams);
}
@NonNull
@Override
public Result doWork() {
String imageUriInput = getInputData().getString("IMAGE_URI");
if(imageUriInput == null) {
return Result.failure();
}
uploadFile(imageUriInput);
return Result.success();
}
...
}
// Create a WorkRequest for your Worker and sending it input
WorkRequest myUploadWork =
new OneTimeWorkRequest.Builder(UploadWork.class)
.setInputData(
new Data.Builder()
.putString("IMAGE_URI", "http://...")
.build()
)
.build();
وبالمثل، يمكنك استخدام فئة Data لإخراج قيمة معادة.
الخطوات التالية
في صفحة الحالات والمراقبة، ستتعرّف على مزيد من المعلومات عن حالات العمل وكيفية تتبُّع مستوى تقدّم عملك.