تناول دليل البدء كيفية إنشاء 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
أكثر ملاءمةً لجدولة
المهام المتكررة على فترات زمنية معيّنة.
جدولة عمل لمرة واحدة
بالنسبة إلى الأعمال البسيطة التي لا تتطلّب أيّ إعدادات إضافية، استخدِم الطريقة static
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>() .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) .build() WorkManager.getInstance(context) .enqueue(request)
Java
OneTimeWorkRequest request = new OneTimeWorkRequestBuilder<T>() .setInputData(inputData) .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) .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
، ما يؤدي إلى إلغاء الطلب في حال عدم توفّر حصة كافية.
نموذج تطبيق
للاطّلاع على مثال كامل على كيفية استخدام WorkManager 2.7.0 للعمل المُسرَّع، اطّلِع على WorkManagerSample على GitHub.
العمل المُعجَّل المؤجَّل
يحاول النظام تنفيذ مهمة مُسرَّعة معيّنة في أقرب وقت ممكن بعد invocation للمهمة. ومع ذلك، كما هو الحال مع الأنواع الأخرى من وظائف المعالجة، قد يُؤجل النظام بدء العمل الجديد المُعجل، مثل الحالات التالية:
- الحمل: يكون الحمل على النظام مرتفعًا جدًا، ما قد يحدث عندما يكون هناك عدد كبير جدًا من المهام التي يتم تنفيذها حاليًا أو عندما لا يتوفّر للنظام ذاكرة كافية.
- الحصة: تم تجاوز الحد الأقصى لحصة المهام المُسرَّعة. يستخدم العمل المُسرَّع نظام حصة يستند إلى مجموعات التطبيقات في وضع الاستعداد ويحدّد الحد الأقصى لوقت التنفيذ خلال فترة زمنية متجدّدة. إنّ الحصص المستخدَمة في العمل المُسرَّع أكثر تقييدًا من تلك المستخدَمة في الأنواع الأخرى من المهام التي تعمل في الخلفية.
جدولة العمل الدوري
قد يتطلّب تطبيقك في بعض الأحيان تنفيذ مهام معيّنة بشكل دوري. على سبيل المثال، قد تحتاج إلى الاحتفاظ بنسخة احتياطية من بياناتك بصفة دورية أو تنزيل محتوى جديد في تطبيقك أو تحميل السجلات إلى خادم.
في ما يلي كيفية استخدام 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();
في هذا المثال، تم جدولة العمل بفاصل زمني قدره ساعة واحدة.
يتم تحديد فترة الفاصل على أنّها الحد الأدنى للوقت بين التكرارات. يعتمد الوقت الدقيق الذي سيتم فيه تنفيذ Worker على القيود التي تستخدمها في عنصر 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
إلى أن يتم استيفاء هذا الشرط. وقد يؤدي ذلك إلى تأخّر تنفيذ عملية معيّنة من عملك أو تخطّيها في حال عدم استيفاء الشروط خلال فاصل التنفيذ.
قيود العمل
تضمن القيود تأجيل العمل إلى أن يتم استيفاء الشروط المثلى. تتوفّر القيود التالية لخدمة WorkManager.
NetworkType | تقييد نوع الشبكة المطلوب لتشغيل عملك
على سبيل المثال، شبكة Wi-Fi (UNMETERED ).
|
BatteryNotLow | عند ضبطها على "صحيح"، لن يتم تنفيذ عملك إذا كان الجهاز في وضع البطارية المنخفضة. |
RequiresCharging | عند ضبطها على "صحيح"، لن يتم تنفيذ عملك إلا عندما يكون الجهاز قيد الشحن. |
DeviceIdle | عند ضبط هذا الخيار على "صحيح"، يجب أن يكون جهاز المستخدم غير نشط قبل تنفيذ العمل. يمكن أن يكون ذلك مفيدًا لتشغيل عمليات مجمّعة قد تؤثر سلبًا في أداء التطبيقات الأخرى التي تعمل بشكل نشط على جهاز المستخدم. |
StorageNotLow | عند ضبط هذا الإعداد على true، لن يتم تشغيل عملك إذا كانت مساحة التخزين للمستخدم على الجهاز منخفضة جدًا. |
لإنشاء مجموعة من القيود وربطها ببعض الأعمال، أنشئ مثيلًا لمحاولة
Constraints
باستخدام Contraints.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()
من Worker. تتم بعد ذلك
إعادة جدولة عملك وفقًا لتأخير التراجع وسياسة التراجع.
يحدِّد تأخُّر الانتظار الحد الأدنى للوقت الذي يجب الانتظار خلاله قبل إعادة محاولة عملك بعد المحاولة الأولى. لا يمكن أن تقل هذه القيمة عن 10 ثوانٍ (أو MIN_BACKOFF_MILLIS).
تحدِّد سياسة الانتظار كيفية زيادة وقت الانتظار بمرور الوقت لمحاولة إعادة المحاولة التالية. يتيح WorkManager سياستَي انتظار، هما
LINEAR
وEXPONENTIAL
.
يتضمّن كل طلب عمل سياسة التراجع وتأخير التراجع. السياسة التلقائية هي EXPONENTIAL
مع تأخير 30 ثانية، ولكن يمكنك إلغاء ذلك في إعدادات طلب العمل.
في ما يلي مثال على تخصيص سياسة ووقت الانتظار في حالة التراجع.
Kotlin
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>() .setBackoffCriteria( BackoffPolicy.LINEAR, OneTimeWorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS) .build()
Java
WorkRequest myWorkRequest = new OneTimeWorkRequest.Builder(MyWork.class) .setBackoffCriteria( BackoffPolicy.LINEAR, OneTimeWorkRequest.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 التي يمكن استخدامها لتحديد حالة العمل الحالية.
يوضّح الرمز التالي كيفية إضافة علامة "cleanup" إلى عملك:
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
لإخراج قيمة معروضة. يتم تناول بيانات الإدخال
والإخراج بمزيد من التفصيل في قسم مَعلمات الإدخال
والقيم المعروضة.
الخطوات التالية
في صفحة الحالات والملاحظات، يمكنك الاطّلاع على مزيد من المعلومات عن حالات العمل وكيفية تتبُّع مستوى تقدّمك.