ניהול העבודה

אחרי שמגדירים 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, ערכים ייחודיים אפשר לשייך את השמות רק למופע אחד של עבודה.

אפשר להחיל עבודות ייחודיות גם על עבודות חד-פעמיות וגם על עבודות תקופתיות. אפשר ליצור רצף עבודה ייחודי באמצעות אחת מהשיטות האלה, בהתאם מתזמנים עבודה חוזרת או עבודה חד-פעמית.

בשתי השיטות האלה מקבלים 3 ארגומנטים:

  • uniqueWorkNameString שמשמש לזיהוי ייחודי של היצירה בקשה.
  • 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 איזו פעולה לבצע יש התנגשות. כדי לעשות זאת, מעבירים 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) // 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 של כל אחד 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: 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 עם הפרמטר אחרים. כל ערך ברכיב הוא 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, כי העובד כבר נחשב הופסק.