במדריך לתחילת העבודה מוסבר איך ליצור 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);
לעבודות מורכבות יותר אפשר להשתמש ב-builder:
Kotlin
val uploadWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<MyWork>() // Additional configuration .build()
Java
WorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(MyWork.class) // Additional configuration .build();
תזמון עבודה מזורזת
המושג WorkManager 2.7.0 השיק את המושג 'עבודה מזורזת'. כך אפשר WorkManager לביצוע עבודה חשובה תוך הענקת שליטה טובה יותר למערכת יותר מדי גישה למשאבים.
עבודה מזורזת לא חשובה למאפיינים הבאים:
- חשיבות: עבודה מזורזת מתאימה למשימות שחשובות למשתמש, או הם ביוזמת המשתמש.
- מהירות: עבודה מזורזת מתאימה בצורה הטובה ביותר למשימות קצרות שמתחילות באופן מיידי. תוך כמה דקות.
- Quotas: מכסה ברמת המערכת שמגבילה את זמן הביצוע בחזית. ההגדרה קובעת אם משימה מזורזת יכולה להתחיל.
- ניהול צריכת חשמל: הגבלות על ניהול צריכת חשמל, כגון סוללה המצבים 'חיסכון' ו'נמנום' צפויים להשפיע פחות על עבודה מזורזת.
- זמן אחזור: המערכת מבצעת באופן מיידי עבודה מזורזת, כל עוד עומס העבודה הנוכחי של המערכת מאפשר לה לעשות זאת. זה אומר שתהליך האחזור רגיש ולא ניתן לתזמן אותו לביצוע במועד מאוחר יותר.
תרחיש לדוגמה לעבודה מזורזת יכול להיות בתוך אפליקציית צ'אט כשהמשתמש רוצה לשלוח הודעה או תמונה מצורפת. באופן דומה, אפליקציה שמטפלת בתהליך תשלום או הרשמה ייתכן גם שתרצו להשתמש בעבודה מזורזת. הדבר מכיוון שהמשימות האלה חשובות למשתמש, מתבצעות במהירות צריכים להתחיל מייד, וצריך להמשיך לבצע אותן גם אם המשתמש סוגר את האפליקציה
מכסות
המערכת חייבת להקצות את זמן הביצוע למשימה מזורזת לפני שהיא יכולות לפעול. זמן הביצוע אינו מוגבל. במקום זאת, כל אפליקציה מקבלת מכסה של זמן הביצוע. כשהאפליקציה משתמשת בזמן הביצוע שלה ומגיע במכסה שהוקצתה, לא ניתן יותר לבצע עבודה מזורזת עד שמגיעים למכסה מתבצע רענון. כך מערכת Android יכולה לאזן בצורה יעילה יותר בין המשאבים השונים תרגום מכונה.
משך זמן הביצוע הזמין לאפליקציה מבוסס על Pendingby bucket (קטגוריית המתנה) והחשיבות של התהליך.
ניתן לקבוע מה קורה כאשר מכסת הביצוע לא מאפשרת משימה מזורזת שתופעל מיידית. יש פרטים נוספים בקטעי הקוד שבהמשך.
ביצוע עבודה מזורזת
החל מגרסה 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
חייב להטמיע את ה-method getForegroundInfo
אם
רוצה לבקש שהמשימה תפעל כמשימה מזורזת.
כשמטרגטים ל-Android מגרסה 12 ואילך, שירותים שפועלים בחזית עדיין זמינים
באמצעות שיטת הsetForeground
המתאימה.
עובד
העובדים לא יודעים אם העבודה שלהם מזורזת או לא. אבל
עובדים יכולים להציג התראה בגרסאות מסוימות של Android כאשר
הבקשה של WorkRequest
הופעלה במהירות.
כדי להפעיל זאת, WorkManager מספק את ה-method getForegroundInfoAsync()
,
שעליך ליישם כדי ש-WorkManager יוכל להציג התראה
ForegroundService
עבורך במקרה הצורך.
עובדי Coroutine
אם משתמשים ב-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.
עבודה מזורזת שנדחתה
המערכת מנסה לבצע משימה מזורזת נתונה בהקדם האפשרי לאחר מופעלת. עם זאת, כמו בסוגי עבודה אחרים, המערכת עשוי לדחות את ההתחלה של עבודה מזורזת חדשה, למשל במקרים הבאים:
- עומס: עומס המערכת גבוה מדי, מה שעלול לקרות כשיש יותר מדי משימות פועלת, או כשאין מספיק זיכרון במערכת.
- Quota (מכסה): חרגתם ממכסת המשימות המואצת. עבודה מזורזת משתמשת במערכת מכסות המבוססת על קטגוריות המתנה של אפליקציה, ומגבילה את הזמן המקסימלי לביצוע בחלון זמן נע. המכסות שמשמשות עבודה מזורזת מגבילה יותר מעבודה מסוגים אחרים עבודות ברקע.
תזמון עבודות תקופתיות
ייתכן שלפעמים האפליקציה תדרוש שעבודות מסוימות יפעלו מדי פעם. לדוגמה, מומלץ לגבות מדי פעם את הנתונים, להוריד תוכן חדש או מעלים יומנים לשרת.
כך משתמשים ב-PeriodicWorkRequest
כדי ליצור
אובייקט WorkRequest
שמופעל מדי פעם:
Kotlin
val saveRequest = PeriodicWorkRequestBuilderS<aveImageToFileWorker(>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 = PeriodicWorkRequestBuilderS<aveImageToFileWorker(> 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.
סוג הרשת | מגבילה את סוג הרשת שנדרש כדי שהעבודה תפעל.
לדוגמה, Wi-Fi (UNMETERED ).
|
סוללה לא נמוכה | אם המדיניות מוגדרת כ-True, העבודה לא תפעל כשהמכשיר נמצא במצב סוללה חלשה. |
נדרשת טעינה | אם המדיניות מוגדרת כ-True, העבודה תפעל רק כשהמכשיר בטעינה. |
DeviceIdle | אם המדיניות מוגדרת כ-True, המכשיר של המשתמש לא יהיה פעיל כדי שהעבודה תתבצע. האפשרות הזו שימושית להרצת פעולות באצווה, שאחרת עלולות להיות להן השפעה שלילית על הביצועים באפליקציות אחרות שפועלות באופן פעיל במכשיר של המשתמש. |
StorageNotLow | אם המדיניות מוגדרת כ-True, העבודה לא תפעל אם נפח האחסון של המשתמש במכשיר נמוך מדי. |
כדי ליצור קבוצת אילוצים ולשייך אותה לעבודה מסוימת,
את המכונה Constraints
באמצעות Contraints.Builder()
ומקצים אותה
WorkRequest.Builder()
.
לדוגמה, הקוד הבא בונה בקשת עבודה שרצה רק כאשר שהמכשיר של המשתמש בטעינה וגם מחובר ל-Wi-Fi:
Kotlin
val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.UNMETERED) .setRequiresCharging(true) .build() val myWorkRequest: WorkRequest = OneTimeWorkRequestBuilderM<yWork(>) .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 = OneTimeWorkRequestBuilderM<yWork(>) .setInitialDelay(10, TimeUnit.MINUTES) .build()
Java
WorkRequest myWorkRequest = new OneTimeWorkRequest.Builder(MyWork.class) .setInitialDelay(10, TimeUnit.MINUTES) .build();
אמנם הדוגמה ממחישה איך להגדיר עיכוב ראשוני
OneTimeWorkRequest
, אפשר גם להגדיר השהיה ראשונית של
PeriodicWorkRequest
. במקרה הזה, רק ההפעלה הראשונה של העבודה התקופתית
יהיה עיכוב.
המדיניות בנושא ניסיון חוזר והשהיה לפני ניסיון חוזר (backoff)
אם דורשים ש-WorkManager יתבצע ניסיון חוזר לעבודה, אפשר להחזיר
Result.retry()
מהעובד שלך. אחרי שתעשו את זה,
נקבע מועד חדש בהתאם לעיכוב לפני ניסיון חוזר ולמדיניות בנושא השהיה לפני ניסיון חוזר.
השהיה לפני ניסיון חוזר מציינת את משך הזמן המינימלי שצריך להמתין לפני ניסיון חוזר את העבודה אחרי הניסיון הראשון. הערך הזה יכול להיות באורך 10 שניות לכל היותר (או MIN_BACKOFF_MILLIS).
מדיניות ההשהיה לפני ניסיון חוזר מגדירה איך עיכוב ההשהיה לפני ניסיון חוזר (backoff) צריך להימשך לאורך זמן ניסיונות חוזרים נוספים. ב-WorkManager יש 2 כללי מדיניות להשהיה לפני ניסיון חוזר (backoff)
LINEAR
והקבוצהEXPONENTIAL
.
לכל בקשת עבודה יש מדיניות השהיה לפני ניסיון חוזר ועיכוב לפני ניסיון חוזר (backoff). מדיניות ברירת המחדל
EXPONENTIAL
עם עיכוב של 30 שניות, אבל ניתן לעקוף זאת
להגדרת בקשות עבודה.
בהמשך מוצגת דוגמה להתאמה אישית של המדיניות והשהיית ההשהיה לפני ניסיון חוזר.
Kotlin
val myWorkRequest = OneTimeWorkRequestBuilderM<yWork(>) .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();
בדוגמה הזו, ההשהיה המינימלית של השהיה לפני ניסיון חוזר (backoff) מוגדרת לערך המינימלי המותר,
10 שניות. מכיוון שהמדיניות היא LINEAR
, מרווח הזמן החוזר יגדל ב-
כ-10 שניות בכל ניסיון חדש. לדוגמה, ההפעלה הראשונה
יתבצע ניסיון סיום עם Result.retry()
שוב אחרי 10 שניות,
ואחריה 20, 30, 40 וכן הלאה, אם היצירה ממשיכה
Result.retry()
לאחר הניסיונות הבאים. אם מדיניות ההשהיה לפני ניסיון חוזר (backoff) הוגדרה
EXPONENTIAL
, הרצף של משך הניסיונות החוזרים יהיה קרוב יותר ל-20, 40, 80, כך
מופעלת.
תיוג עבודה
לכל בקשת עבודה יש מזהה ייחודי, שיכול לשמש כדי לזהות שהוגדרו מאוחר יותר כדי לבטל את העבודה או לצפות בהתקדמות.
אם יש לכם קבוצה של עבודות שקשורות באופן לוגי, אולי תוכלו לעזור לתייג את פריטי העבודה האלה. התיוג מאפשר לך לפעול בקבוצת עבודה יחד.
לדוגמה, WorkManager.cancelAllWorkByTag(String)
מבטל
את כל בקשות העבודה עם תג מסוים, וגם
הפונקציה WorkManager.getWorkInfosByTag(String)
מחזירה רשימה של
אובייקטים של WorkInfo שבהם אפשר להשתמש כדי לקבוע את מצב העבודה הנוכחי.
הקוד הבא מראה איך מוסיפים 'ניקוי' תג ליצירה שלך:
Kotlin
val myWorkRequest = OneTimeWorkRequestBuilderM<yWork(>) .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 = OneTimeWorkRequestBuilderU<ploadWork(>) .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
כדי ליצור פלט של ערך מוחזר. קלט ו
מידע מפורט יותר על נתוני הפלט בסעיף פרמטרים של קלט
מוחזרים ערכים.
השלבים הבאים
בדף מדינות ותצפית מופיע מידע נוסף על מצבי עבודה ואיך לעקוב אחר התקדמות העבודה שלכם.