אחרי שמגדירים
Worker
וגם
WorkRequest
שלך,
השלב האחרון הוא להכניס את העבודה לתור. הדרך הפשוטה ביותר להוסיף עבודה לתור
היא לקרוא ל-method 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. ביטול הלייק tags, ערכים ייחודיים אפשר לשייך את השמות רק למופע אחד של עבודה.
אפשר להחיל עבודות ייחודיות גם על עבודות חד-פעמיות וגם על עבודות תקופתיות. אפשר ליצור רצף עבודה ייחודי באמצעות אחת מהשיטות האלה, בהתאם מתזמנים עבודה חוזרת או עבודה חד-פעמית.
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 איזו פעולה לבצע יש התנגשות. כדי לעשות זאת, מעבירים enum בזמן הוספת העבודה לתור.
לעבודה חד-פעמית עליך לספק
ExistingWorkPolicy
,
תומך ב-4 אפשרויות לטיפול בהתנגשות.
REPLACE
קיימים כדי לעבוד עם היצירה החדשה. אם בוחרים באפשרות הזו, המערכת מבטלת את העבודה הקיימת.KEEP
עבודות קיימות וגם מתעלמים מהיצירה החדשה.APPEND
את העבודה החדשה של הסוף של העבודה הקיימת. המדיניות הזו תגדיר את היצירה החדשה שלכם משורשרות בעבודה הקיימת.
היצירה הקיימת הופכת לדרישה מוקדמת ליצירה החדשה. אם הערכים הקיימים
הופך ל-CANCELLED
או FAILED
, היצירה החדשה היא גם CANCELLED
או FAILED
.
אם אתם רוצים שהעבודה החדשה תפעל בלי קשר לסטטוס של העבודה הקיימת:
במקומה צריך להשתמש במדיניות APPEND_OR_REPLACE
.
APPEND_OR_REPLACE
פועלת באופן דומה ל-APPEND
, אבל היא לא תלויה סטטוס עבודה דרישות מוקדמות. אם היצירה הקיימת היאCANCELLED
אוFAILED
, העבודה החדשה עדיין פועלת.
לעבודה תקופתית צריך לספק
ExistingPeriodicWorkPolicy
שתומך ב-2 אפשרויות: REPLACE
ו-KEEP
. האפשרויות האלה פועלות באופן זהה
כמקבילות שלהן.
צפייה בעבודה שלך
בכל שלב אחרי שמוסיפים את העבודה לתור, אפשר לבדוק את הסטטוס שלה
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
של כל אחד
methods שמאפשרות לך לצפות בשינויים ב-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(); } });
שאילתות מורכבות לעבודה
ב-WorkManager 2.4.0 ואילך תומך בשאילתות מורכבות עבור משימות ממתינות באמצעות
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);
כל רכיב (תג, מצב או שם) ב-WorkQuery
משתנה ל-AND
עם הפרמטר
אחרים. כל ערך ברכיב הוא edOR
. לדוגמה: (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()
מומלץ לשנות את השיטה הזו כדי לטפל בכל ניקוי פוטנציאלי. איך עוצרים
run worker כדי לקבל מידע נוסף.
הפסקת Worker פעיל
יש כמה סיבות אפשריות לכך שהרצת Worker
על ידי WorkManager הופסקה:
- ביקשת במפורש לבטל את ההזמנה (על ידי התקשרות
WorkManager.cancelWorkById(UUID)
, למשל). - במקרה של יצירה ייחודית,
צירפת באופן מפורש מכשיר
WorkRequest
חדש עםExistingWorkPolicy
מתוךREPLACE
. המינוי הישן שלWorkRequest
נחשב מיד כמבוטל. - העבודה שלכם כבר לא עומדת במגבלות שהגדרתם.
- המערכת הורתה לאפליקציה שלך להפסיק את העבודה מסיבה כלשהי. מי יכול יקרה אם תחרגו מהמועד האחרון לביצוע של 10 דקות. העבודה היא מתוזמן לניסיון חוזר במועד מאוחר יותר.
בתנאים האלה, ה-Worker שלכם יופסק.
עליך לבטל בשיתוף פעולה כל עבודה שהייתה לך כרגע ולשחרר כל עבודה למשאבים שמוחזקים על ידי ה-Worker. לדוגמה, צריך לסגור את בשלב הזה למסדי נתונים וקבצים. יש שני מנגנונים כדי להבין מתי העובד שלך מפסיק לעבוד.
קריאה חוזרת (callback) מסוג onSped()
הפעלה של WorkManager
ListenableWorker.onStopped()
ברגע שה-Worker שלך הופסק. כדי לסגור, צריך לשנות את השיטה הזו
ולא במשאבים שאתם משקיעים.
המאפיין isSStop()
אפשר לקרוא ל-
ListenableWorker.isStopped()
כדי לבדוק אם העובד כבר עצר. אם אתם
ביצוע פעולות ממושכות או פעולות שחוזרות על עצמן אצל ה-Worker,
כדאי לבדוק את הנכס הזה לעיתים קרובות ולהשתמש בו כאות להפסקת העבודה מיד
ככל האפשר.
הערה: Work Manager מתעלם
Result
הוגדר על ידי Worker
שקיבל את אות onStop, כי העובד כבר נחשב
הופסק.