Lab Lab זה הוא חלק מקורס Android Kotlin Fundamentals. כדי להפיק את המקסימום מהקורס הזה, יש לפעול ברצף לפי קודי שיעור ה-Lab. כל שיעורי Lab של הקורסים מופיעים בדף הנחיתה של Lab Kotlin Fundamentals ל-Android Lab.
מבוא
רוב האפליקציות בעולם האמיתי צריכות לבצע משימות ארוכות של רקע. לדוגמה, אפליקציה יכולה להעלות קבצים לשרת, לסנכרן נתונים משרת ולשמור אותם במסד נתונים של Room
, לשלוח יומנים לשרת או לבצע פעולות יקרות בנתונים. יש לבצע את הפעולות האלה ברקע, מחוץ לשרשור של ממשק המשתמש (השרשור הראשי). משימות ברקע צורכות משאבים מוגבלים של המכשיר, כמו RAM וסוללה. אם חוויית המשתמש לא תטופל כראוי, היא עלולה לפגוע בחוויית המשתמש.
בשיעור ה-Lab הזה תלמדו איך להשתמש בWorkManager
כדי לקבוע משימה ברקע בצורה יעילה ויעילה. מידע נוסף על פתרונות זמינים אחרים לעיבוד ברקע ב-Android זמין במאמר מדריך לעיבוד רקע.
דברים שחשוב לדעת
- כיצד להשתמש ברכיבי הארכיטקטורה של Android מסוג
ViewModel
,LiveData
ו-Room
. - איך מבצעים טרנספורמציות בכיתה
LiveData
? - איך בונים ומפעילים שגרה.
- איך להשתמש במתאמים מחייבים בקישור נתונים.
- איך לטעון נתונים שנשמרו במטמון באמצעות דפוס של מאגר.
מה תלמדו
- איך יוצרים
Worker
, שמייצג יחידת עבודה? - איך ליצור
WorkRequest
כדי לבקש עבודה. - איך להוסיף מגבלות ל-
WorkRequest
כדי להגדיר איך ומתי העובד יפעל. - איך משתמשים ב-
WorkManager
כדי לקבוע משימות ברקע.
הפעולות שתבצעו:
- יש ליצור עובד כדי לבצע משימת רקע כדי לאחזר מראש את הפלייליסט של סרטוני DevBytes מהרשת.
- מתזמנים את העבודה של העובד מדי פעם.
- עליך להוסיף מגבלות על
WorkRequest
. - תזמון של
WorkRequest
תקופתי מדי פעם.
בשיעור Lab זה אתם עובדים על אפליקציית DevBytes שפיתחתם במעבדת קוד קודמת. (אם האפליקציה לא מותקנת במכשיר שלך, אפשר להוריד את קוד ההתחלה לשיעור הזה).
האפליקציה DevBytes מציגה רשימה של סרטוני DevByte, שהם מדריכים קצרים שנוצרו על ידי צוות הקשרים של מפתחים ב-Google Android. הסרטונים כוללים תכונות למפתחים ושיטות מומלצות לפיתוח Android.
אתם משפרים את חוויית המשתמש באפליקציה על ידי שליפה מוקדמת של סרטונים פעם ביום. כך ניתן להבטיח שהמשתמש יקבל תוכן חדש ברגע שהוא יפתח את האפליקציה.
במשימה הזו צריך להוריד ולבדוק את הקוד למתחילים.
שלב 1: הורדה והפעלה של האפליקציה למתחילים
תוכלו להמשיך לעבוד דרך אפליקציית DevBytes שיצרתם ב-codelab הקודם (אם היא מותקנת). לחלופין, אפשר להוריד את האפליקציה למתחילים.
במשימה זו אתם מורידים ומפעילים את האפליקציה למתחילים ובודקים את הקוד למתחילים.
- אם עוד לא התקנת את אפליקציית DevBytes, יש להוריד את קוד פיתוח ה-DevBytes למעבדת הקוד הזו מפרויקט DevBytesRepository מ-GitHub.
- מבטלים את דחיסת הקוד ופותחים את הפרויקט ב-Android Studio.
- מחברים את מכשיר הבדיקה או את האמולטור לאינטרנט אם הוא עדיין לא מחובר. לבנות ולהפעיל את האפליקציה. האפליקציה מאחזרת את רשימת הסרטונים של DevByte מהרשת ומציגה אותם.
- באפליקציה, מקישים על סרטון כלשהו כדי לפתוח אותו באפליקציית YouTube.
שלב 2: מגלים את הקוד
האפליקציה למתחילים מגיעה עם הרבה קוד שהוכנס במעבדה הקודמת. לקוד הפתיחה של קוד Lab זה יש מודולים של רשת, ממשק משתמש, מטמון לא מקוון ומאגרי נתונים. אפשר להתמקד בתזמון המשימה ברקע באמצעות WorkManager
.
- ב-Android Studio, מרחיבים את כל החבילות.
- לעיון בחבילה של
database
. החבילה מכילה את הישויות של מסד הנתונים ומסד הנתונים המקומי, שמוטמע באמצעותRoom
. - לעיון בחבילה של
repository
. החבילה מכילה את המחלקהVideosRepository
שמסירה את שכבת הנתונים משאר האפליקציה. - בודקים את שאר קוד ההתחלה בעצמכם, בעזרת העזרה של קוד הקוד הקודם.
WorkManager
הוא אחד מרכיבי הארכיטקטורה של Android והוא חלק מJet Jetpack. WorkManager
מיועד לעבודה ברקע שניתנת להגנה ונדרשת הפעלה מובטחת:
- המשמעות של ניתן לדחייה היא שהיצירה לא נדרשת להרצה מיד. לדוגמה, שליחת נתונים אנליטיים לשרת או סנכרון מסד הנתונים ברקע היא עבודה שניתן לדחות אותה.
- ביצוע משימות מובטחות פירושו שהמשימה תפעל גם אם האפליקציה תצא או אם המכשיר יופעל מחדש.
אפליקציית WorkManager
פועלת ברקע, אבל היא מטפלת בבעיות תאימות ובשיטות מומלצות לתקינות הסוללה ותקינות המערכת. WorkManager
מציע תאימות לרמת API 14. WorkManager
בוחר דרך מתאימה לתזמון משימה ברקע, בהתאם לרמת ה-API במכשיר. היא עשויה להשתמש ב-JobScheduler
(ב-API מגרסה 23 ואילך) או בשילוב של AlarmManager
עם BroadcastReceiver
.
WorkManager
גם מאפשר להגדיר קריטריונים לזמן שבו משימת הרקע פועלת. לדוגמה, ייתכן שתרצו שהמשימה תפעל רק כאשר סטטוס הסוללה, סטטוס הרשת או מצב הטעינה עומדים בקריטריונים מסוימים. בהמשך תלמדו איך להגדיר אילוצים.
במעבדה זו, אתם מתזמנים משימה לאחזר מראש את פלייליסט הסרטונים של DevBytes מהרשת פעם ביום. אפשר לקבוע את המשימה הזו באמצעות הספרייה של WorkManager
.
- פותחים את הקובץ
build.gradle (Module:app)
ומוסיפים את התלות שלWorkManager
בפרויקט.
אם משתמשים בגרסה האחרונה של הספרייה, אפליקציית הפתרון צריכה להיאסף כצפוי. אם הבעיה לא נפתרה, נסו לפתור את הבעיה או לחזור לגרסת הספרייה שמופיעה למטה.
// WorkManager dependency
def work_version = "1.0.1"
implementation "android.arch.work:work-runtime-ktx:$work_version"
- צריך לסנכרן את הפרויקט ולוודא שאין שגיאות הידור.
לפני שמוסיפים קוד לפרויקט, חשוב להכיר את הכיתות הבאות בספרייה WorkManager
:
Worker
הכיתה הזו היא המקום שבו מגדירים את העבודה בפועל (המשימה) ברקע. הרחבת הכיתה תבטל את השיטהdoWork()
. השיטהdoWork()
היא המקום שבו מוסיפים את הקוד לביצוע ברקע, כמו סנכרון נתונים עם השרת או עיבוד תמונות. הטמעת אתWorker
במשימה הזו.WorkRequest
הכיתה הזו מייצגת בקשה להפעלת העובד ברקע. בעזרתWorkRequest
אפשר להגדיר איך ומתי להריץ את משימת העובד, בעזרתConstraints
, כמו המכשיר מחובר או Wi-Fi מחובר. הטמעת אתWorkRequest
במשימה מאוחרת יותר.WorkManager
הכיתה הזו קובעת לוח זמנים ומריצה אתWorkRequest
.WorkManager
מתזמנים בקשות עבודה באופן שמחלק את העומס על משאבי המערכת, תוך שמירה על האילוצים שציינתם. הטמעת אתWorkManager
במשימה מאוחרת יותר.
שלב 1: יצירת עובד
במשימה הזו מוסיפים Worker
כדי לאחזר מראש את הפלייליסט של סרטוני DevBytes.
- בתוך החבילה
devbyteviewer
, יש ליצור חבילה חדשה בשםwork
. - בתוך החבילה
work
, יש ליצור כיתה חדשה של Kotlin שנקראתRefreshDataWorker
. - הרחבת הכיתה של
RefreshDataWorker
מהכיתהCoroutineWorker
. צריך להעביר אתcontext
ואתWorkerParameters
כפרמטרים של הרכבה.
class RefreshDataWorker(appContext: Context, params: WorkerParameters) :
CoroutineWorker(appContext, params) {
}
- כדי לפתור את השגיאה של הכיתה המופשטת, יש לבטל את השיטה
doWork()
בתוך הכיתהRefreshDataWorker
.
override suspend fun doWork(): Result {
return Result.success()
}
פונקציית השעיה היא פונקציה שניתן להשהות ולהמשיך אותה מאוחר יותר. פונקציית השעיה יכולה לבצע פעולה ממושכת, ולהמתין שהתהליך יסתיים בלי לחסום את השרשור הראשי.
שלב 2: הטמעת DoWork()
השיטה doWork()
בתוך הכיתה Worker
מופעלת בשרשור ברקע. השיטה פועלת באופן סינכרוני והיא אמורה להחזיר אובייקט ListenableWorker.Result
. מערכת Android מספקת ל-Worker
10 דקות לכל היותר עד לסיום הביצוע ומחזירה אובייקט ListenableWorker.Result
. בתום פרק הזמן הזה, המערכת מפסיקה את ההפעלה של Worker
.
כדי ליצור אובייקט ListenableWorker.Result
, יש לקרוא לאחת מהשיטות הסטטיסטיות הבאות כדי לציין את סטטוס ההשלמה של פעילות הרקע:
Result.success()
– העבודה הושלמה.Result.failure()
—העבודה הושלמה עם כשל קבוע.Result.retry()
—העבודה נכשלה באופן זמני ויש לנסות שוב.
במשימה הזו, תטמיעו את השיטה doWork()
כדי לאחזר את הפלייליסט של סרטוני DevBytes מהרשת. ניתן להשתמש שוב בשיטות הקיימות בכיתה VideosRepository
כדי לאחזר את הנתונים מהרשת.
- בכיתה
RefreshDataWorker
, בתוךdoWork()
, יוצרים אובייקטVideosDatabase
ואובייקטVideosRepository
והופכים אותו לאובייקט.
override suspend fun doWork(): Result {
val database = getDatabase(applicationContext)
val repository = VideosRepository(database)
return Result.success()
}
- בכיתה
RefreshDataWorker
, בתוךdoWork()
, מעל להצהרהreturn
, יש להתקשר לשיטהrefreshVideos()
בתוך בלוקtry
. צריך להוסיף יומן כדי לעקוב אחרי הזמן שבו העובד פועל.
try {
repository.refreshVideos( )
Timber.d("Work request for sync is run")
} catch (e: HttpException) {
return Result.retry()
}
כדי לפתור את השגיאה &"הפניה שלא נפתרה;" יש לייבא את retrofit2.HttpException
.
- הנה הכיתה המלאה של
RefreshDataWorker
לעיונך:
class RefreshDataWorker(appContext: Context, params: WorkerParameters) :
CoroutineWorker(appContext, params) {
override suspend fun doWork(): Result {
val database = getDatabase(applicationContext)
val repository = VideosRepository(database)
try {
repository.refreshVideos()
} catch (e: HttpException) {
return Result.retry()
}
return Result.success()
}
}
Worker
מגדיר יחידת עבודה והמאפיין WorkRequest
מגדיר איך ומתי כדאי להריץ את העבודה. יש שתי הטמעות בטון של הכיתה WorkRequest
:
- הכיתה
OneTimeWorkRequest
מיועדת למשימות חד-פעמיות. (משימה חד-פעמית מתרחשת רק פעם אחת.) - הכיתה
PeriodicWorkRequest
כוללת עבודות תקופתיות, שחוזרות על עצמן במרווחי זמן.
המשימות יכולות להיות חד-פעמיות או תקופתיות, לכן צריך לבחור את הכיתה בהתאם. למידע נוסף על תזמון עבודה חוזרת, עיינו בתיעוד העבודה החוזר.
במשימה הזו, צריך להגדיר WorkRequest
כדי להריץ את העובד שיצרת במשימה הקודמת ולתזמן אותו.
שלב 1: הגדרת עבודה חוזרת
בתוך אפליקציית Android, המחלקה Application
היא המחלקה הבסיסית שמכילה את כל הרכיבים האחרים, כגון פעילויות ושירותים. כשיוצרים תהליך עבור האפליקציה או החבילה, נוצרת מחלקת Application
(או כל סיווג משנה אחר של Application
) לפני כל מחלקה אחרת.
באפליקציה לדוגמה, המחלקה DevByteApplication
היא סיווג משנה של המחלקה Application
. הכיתה DevByteApplication
היא מקום טוב לקבוע את WorkManager
.
- בכיתה
DevByteApplication
, יוצרים שיטה שנקראתsetupRecurringWork()
כדי להגדיר את העבודה החוזרת ברקע.
/**
* Setup WorkManager background job to 'fetch' new network data daily.
*/
private fun setupRecurringWork() {
}
- בשיטה
setupRecurringWork()
, יוצרים ומתחילים בקשת עבודה תקופתית פעם ביום, באמצעות השיטהPeriodicWorkRequestBuilder()
. יש לעבור את הכיתהRefreshDataWorker
שיצרת במשימה הקודמת. מרווח זמן של1
עם יחידת זמןTimeUnit.
DAYS
.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.build()
כדי לפתור את השגיאה, צריך לייבא את java.util.concurrent.TimeUnit
.
שלב 2: תזמון WorkRequest עם WorkManager
אחרי שמגדירים את WorkRequest
, אפשר לתזמן אותו עם WorkManager
באמצעות השיטה enqueueUniquePeriodicWork()
. שיטה זו מאפשרת להוסיף ל'הבאים בתור' PeriodicWorkRequest
שמות ייחודיים, שבהם אפשר להפעיל רק PeriodicWorkRequest
אחד מתוך שם מסוים בכל פעם.
לדוגמה, ייתכן שתרצו להפעיל רק פעולת סנכרון אחת. אם פעולת סנכרון אחת נמצאת בהמתנה, תוכלו לבחור אם להפעיל אותה או להחליף אותה בעבודה החדשה באמצעות existingperiodicWorkPolicy.
לקבלת מידע נוסף על הדרכים לתזמן WorkRequest
, יש לעיין בתיעוד של WorkManager
.
- בכיתה
RefreshDataWorker
, בתחילת הכיתה, מוסיפים אובייקט נלווה. יש להגדיר שם עבודה כדי לזהות את העובד הזה באופן ייחודי.
companion object {
const val WORK_NAME = "com.example.android.devbyteviewer.work.RefreshDataWorker"
}
- בקורס '
DevByteApplication
' בסוף שיטתsetupRecurringWork()
, מתזמנים את העבודה באמצעות השיטהenqueueUniquePeriodicWork()
. יש לעבור ברמתKEEP
עבור ה- נקודות נקודות קיימות. יש להעביר את הפרמטרrepeatingRequest
כפרמטרPeriodicWorkRequest
.
WorkManager.getInstance().enqueueUniquePeriodicWork(
RefreshDataWorker.WORK_NAME,
ExistingPeriodicWorkPolicy.KEEP,
repeatingRequest)
אם קיימת עבודה בהמתנה (שלא הושלמה) עם אותו שם, הפרמטר ExistingPeriodicWorkPolicy.
KEEP
גורם ל-WorkManager
לשמור את היצירה המחזורית הקודמת ולמחוק את בקשת העבודה החדשה.
- בתחילת הכיתה
DevByteApplication
, יוצרים אובייקטCoroutineScope
. צריך להעביר את הפרמטרDispatchers.Default
כפרמטר של ה-constructor.
private val applicationScope = CoroutineScope(Dispatchers.Default)
- בשיעור
DevByteApplication
, מוסיפים שיטה חדשה בשםdelayedInit()
כדי להתחיל שגרה.
private fun delayedInit() {
applicationScope.launch {
}
}
- בתוך השיטה
delayedInit()
, יש להתקשר אלsetupRecurringWork()
. - צריך להעביר את אתחול העץ מהשיטה
onCreate()
לשיטתdelayedInit()
.
private fun delayedInit() {
applicationScope.launch {
Timber.plant(Timber.DebugTree())
setupRecurringWork()
}
}
- בכיתה
DevByteApplication
, בסוף השיטהonCreate()
, צריך להוסיף קריאה לשיטהdelayedInit()
.
override fun onCreate() {
super.onCreate()
delayedInit()
}
- פותחים את החלונית Logcat בתחתית החלון של Android Studio. סינון לפי
RefreshDataWorker
. - כדאי להפעיל את האפליקציה. האפליקציה
WorkManager
מתזמנת את העבודה החוזרת שלך באופן מיידי.
בחלונית Logcat , שימו לב להצהרות היומן שמוכיחות שבקשת העבודה מתוזמנת, ולאחר מכן פועלת בהצלחה.
D/RefreshDataWorker: Work request for sync is run I/WM-WorkerWrapper: Worker result SUCCESS for Work [...]
היומן WM-WorkerWrapper
מוצג מספריית WorkManager
, כך שאי אפשר לשנות את הודעת היומן הזו.
שלב 3: (אופציונלי) קובעים מרווח זמן מינימלי ל-WorkRequest
בשלב זה מפחיתים את מרווח הזמן מיום אחד ל-15 דקות. פעולה זו מאפשרת להציג את היומנים של בקשת עבודה תקופתית בפעולה.
- בכיתה
DevByteApplication
, בתוך השיטהsetupRecurringWork()
, יש להגיב על ההגדרה הנוכחיתrepeatingRequest
. הוספה של בקשת עבודה חדשה עם מרווח תקופתי של15
דקות.
// val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
// .build()
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
.build()
- פותחים את החלונית Logcat ב-Android Studio ומסננים לפי
RefreshDataWorker
. כדי לנקות את היומנים הקודמים, לוחצים על ניקוי יומן רישום.
- יש לך אפשרות להריץ את האפליקציה, ומערכת
WorkManager
מתזמנת את העבודה החוזרת שלך באופן מיידי. בחלונית Logcat , שימו לב ליומנים – בקשת העבודה פועלת פעם ב-15 דקות. ממתינים 15 דקות כדי לראות קבוצה נוספת של יומני בקשות עבודה. ניתן להשאיר את האפליקציה פעילה או לסגור אותה. מנהל העבודה אמור להמשיך לפעול.
לתשומת ליבך, לפעמים המרווח קצר מ-15 דקות, ולפעמים יותר מ-15 דקות. (התזמון המדויק כפוף לאופטימיזציות של הסוללה של מערכת ההפעלה).
12:44:40 D/RefreshDataWorker: Work request for sync is run 12:44:40 I/WM-WorkerWrapper: Worker result SUCCESS for Work 12:59:24 D/RefreshDataWorker: Work request for sync is run 12:59:24 I/WM-WorkerWrapper: Worker result SUCCESS for Work 13:15:03 D/RefreshDataWorker: Work request for sync is run 13:15:03 I/WM-WorkerWrapper: Worker result SUCCESS for Work 13:29:22 D/RefreshDataWorker: Work request for sync is run 13:29:22 I/WM-WorkerWrapper: Worker result SUCCESS for Work 13:44:26 D/RefreshDataWorker: Work request for sync is run 13:44:26 I/WM-WorkerWrapper: Worker result SUCCESS for Work
מעולה! יצרת עובד אחד ותזמנת את בקשת העבודה עם WorkManager
. אבל יש בעיה: לא ציינת אילוצים. WorkManager
יתזמן את העבודה פעם ביום, גם אם המכשיר חלשה, במצב שינה או שאין לו חיבור לרשת. הייתה לכך השפעה על הסוללה של המכשיר ועל הביצועים שלו, וחוויית המשתמש תהיה גרועה.
במשימה הבאה תטפלו בבעיה על ידי הוספת אילוצים.
במשימה הקודמת, השתמשת ב-WorkManager
כדי לתזמן בקשת עבודה. במשימה הזו מוסיפים קריטריונים לזמן ביצוע העבודה.
כשמגדירים את WorkRequest
, אפשר לציין אילוצי זמן להפעלת Worker
. לדוגמה, אפשר לציין שהעבודה תבוצע רק כשהמכשיר לא פעיל או רק כשהמכשיר מחובר ל-Wi-Fi ומחובר אליו. אפשר גם לציין מדיניות לגבי ניסיון חוזר. האילוצים הנתמכים הם השיטות המוגדרות ב-Constraints.Builder
. למידע נוסף: הגדרת הבקשות לעבודה.
שלב 1: מוסיפים אובייקט אילוץ ומגדירים אילוץ אחד
בשלב זה, יוצרים אובייקט Constraints
ומגדירים אילוץ אחד לאובייקט, מגבלה על סוג הרשת. (קל יותר לזהות את היומנים באמצעות מגבלה אחת בלבד. בשלב מאוחר יותר מוסיפים עוד אילוצים).
- בכיתה
DevByteApplication
, בתחילתsetupRecurringWork()
, צריך להגדירval
מסוגConstraints
. יש להשתמש בשיטהConstraints.Builder()
.
val constraints = Constraints.Builder()
כדי לפתור את השגיאה, צריך לייבא את androidx.work.Constraints
.
- יש להשתמש בשיטה
setRequiredNetworkType()
כדי להוסיף אילוץ של סוג רשת לאובייקטconstraints
. צריך להשתמש ב-UNMETERED
enum כדי שבקשת העבודה תפעל רק כשהמכשיר מחובר לרשת שלא נמדדת.
.setRequiredNetworkType(NetworkType.UNMETERED)
- יש להשתמש בשיטה
build()
כדי ליצור אילוצים מהבונה.
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.build()
עכשיו עליך להגדיר את האובייקט Constraints
החדש לבקשת העבודה.
- בכיתה
DevByteApplication
, במסגרת השיטהsetupRecurringWork()
, מגדירים את האובייקטConstraints
לבקשת העבודה המחזורית,repeatingRequest
. כדי להגדיר אילוצים, יש להוסיף את השיטהsetConstraints()
מעל הקריאה לשיטהbuild()
.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
.setConstraints(constraints)
.build()
שלב 2: מריצים את האפליקציה ושמים לב ליומנים
בשלב זה אתם מריצים את האפליקציה ושמים לב לכך שבקשות העבודה המוגבלות פועלות ברקע במרווחים.
- כדי לבטל משימות שתוזמנו בעבר, יש להסיר את האפליקציה מהמכשיר או מהאמולטור.
- פותחים את החלונית Logcat ב-Android Studio. בחלונית Logcat , לוחצים על הסמל Clear logcat כדי לנקות את היומנים הקודמים
. סינון לפי
work
. - יש להשבית את ה-Wi-Fi במכשיר או באמולטור כדי לראות כיצד אילוצים פועלים. הקוד הנוכחי מגדיר אילוץ אחד בלבד, ופירושו שהבקשה צריכה לפעול רק ברשת שאינה נמדדת. מכיוון שאין חיבור ל-Wi-Fi, המכשיר לא מחובר לרשת, נמדד או לא נמדד. לכן האילוץ הזה לא יעמוד.
- מריצים את האפליקציה ושמים לב לחלונית Logcat . ה-
WorkManager
לתזמן את משימת הרקע באופן מיידי. המשימה לא מופעלת בגלל אילוץ הרשת.
11:31:44 D/DevByteApplication: Periodic Work request for sync is scheduled
- מפעילים את ה-Wi-Fi במכשיר או באמולטור וצופים בחלונית Logcat . עכשיו משימת הרקע המתוזמנת פועלת בערך 15 דקות, כל עוד היא עומדת במגבלת הרשת.
11:31:44 D/DevByteApplication: Periodic Work request for sync is scheduled 11:31:47 D/RefreshDataWorker: Work request for sync is run 11:31:47 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 11:46:45 D/RefreshDataWorker: Work request for sync is run 11:46:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 12:03:05 D/RefreshDataWorker: Work request for sync is run 12:03:05 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 12:16:45 D/RefreshDataWorker: Work request for sync is run 12:16:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 12:31:45 D/RefreshDataWorker: Work request for sync is run 12:31:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 12:47:05 D/RefreshDataWorker: Work request for sync is run 12:47:05 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 13:01:45 D/RefreshDataWorker: Work request for sync is run 13:01:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...]
שלב 3: מוסיפים אילוצים נוספים
בשלב זה מוסיפים את המגבלות הבאות ל-PeriodicWorkRequest
:
- הסוללה לא חלשה.
- המכשיר בטעינה.
- מכשיר לא פעיל; זמין רק ברמת API 23 (Android M) ואילך.
מיישמים את האפשרויות הבאות בכיתה DevByteApplication
.
- במחלקה
DevByteApplication
, בתוך השיטהsetupRecurringWork()
, יש לציין שבקשת העבודה צריכה לפעול רק אם רמת הטעינה של הסוללה נמוכה. עליך להוסיף את האילוץ לפני הקריאה לשיטתbuild()
, ולהשתמש בשיטהsetRequiresBatteryNotLow()
.
.setRequiresBatteryNotLow(true)
- יש לעדכן את בקשת העבודה כך שהיא תרוץ רק כשהמכשיר בטעינה. עליך להוסיף את האילוץ לפני הקריאה לשיטת
build()
, ולהשתמש בשיטהsetRequiresCharging()
.
.setRequiresCharging(true)
- יש לעדכן את בקשת העבודה כך שהיא תרוץ רק כשהמכשיר לא פעיל. עליך להוסיף את האילוץ לפני הקריאה לשיטת
build()
, ולהשתמש בשיטהsetRequiresDeviceIdle()
. המגבלה הזו מפעילה את בקשת העבודה רק כשהמשתמש לא משתמש במכשיר באופן פעיל. התכונה הזו זמינה רק ב-Android מגרסה 6.0 (Marshmallow) ואילך, לכן צריך להוסיף תנאי לגרסה SDK מגרסהM
ואילך.
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setRequiresDeviceIdle(true)
}
}
זוהי ההגדרה המלאה של האובייקט constraints
.
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresBatteryNotLow(true)
.setRequiresCharging(true)
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setRequiresDeviceIdle(true)
}
}
.build()
- בתוך השיטה
setupRecurringWork()
, משנים את מרווח הבקשות חזרה פעם ביום.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.setConstraints(constraints)
.build()
כאן מיושמת השיטה המלאה של setupRecurringWork()
, עם יומן כדי שתוכלו לעקוב אחר התזמון של בקשת העבודה המחזורית.
private fun setupRecurringWork() {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresBatteryNotLow(true)
.setRequiresCharging(true)
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setRequiresDeviceIdle(true)
}
}
.build()
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.setConstraints(constraints)
.build()
Timber.d("Periodic Work request for sync is scheduled")
WorkManager.getInstance().enqueueUniquePeriodicWork(
RefreshDataWorker.WORK_NAME,
ExistingPeriodicWorkPolicy.KEEP,
repeatingRequest)
}
- כדי להסיר את בקשת העבודה המתוזמנת בעבר, צריך להסיר את האפליקציה DevBytes מהמכשיר או מהאמולטור.
- מריצים את האפליקציה, ו-
WorkManager
מתזמנים מיד את בקשת העבודה. בקשת העבודה פועלת פעם ביום, כאשר כל האילוצים מתקיימים. - בקשת העבודה הזו תרוץ ברקע כל עוד האפליקציה מותקנת, גם אם האפליקציה לא פועלת. מסיבה זו, עליך להסיר את האפליקציה מהטלפון.
כל הכבוד! יישמת וקבעת בקשת עבודה ידידותית לסוללה לצורך שליפה יומית של סרטונים באפליקציית DevBytes. WorkManager
יתזמן ויריץ את העבודה, תוך אופטימיזציה של משאבי המערכת. המשתמשים שלך והסוללות שלהם יהיו שמחים מאוד.
פרויקט ב-Android Studio: DevBytesWorkManager.
- ממשק ה-API של
WorkManager
מאפשר לתזמן משימות אסינכרוניות הניתנות להפעלה באופן אמין. - רוב האפליקציות בעולם האמיתי צריכות לבצע משימות ארוכות של רקע. כדי לתזמן משימה ברקע באופן אופטימלי ויעיל, יש להשתמש ב-
WorkManager
. - הכיתות העיקריות בספרייה של
WorkManager
הןWorker
,WorkRequest
ו-WorkManager
. - הכיתה
Worker
מייצגת יחידת עבודה. כדי להטמיע את משימת הרקע, יש להרחיב את הכיתהWorker
ולעקוף את השיטהdoWork()
. - הכיתה
WorkRequest
מייצגת בקשה לביצוע יחידת עבודה.WorkRequest
היא סיווג הבסיס לציון פרמטרים של עבודה שתזמנת ב-WorkManager
. - יש שתי הטמעות ממשיות של הכיתה
WorkRequest
:OneTimeWorkRequest
למשימות חד-פעמיות ו-PeriodicWorkRequest
לבקשות עבודה תקופתיות. - כשמגדירים את
WorkRequest
, אפשר לצייןConstraints
שיציין מתי ה-Worker
צריך לפעול. המגבלות כוללות, למשל, אם המכשיר מחובר לחשמל, אם המכשיר לא פעיל או אם Wi-Fi מחובר. - כדי להוסיף אילוצים ל-
WorkRequest
, יש להשתמש בשיטות שהוגדרו המפורטות בתיעוד שלConstraints.Builder
. לדוגמה, כדי לציין שה-WorkRequest
לא צריך לפעול אם סוללת המכשיר חלשה, יש להשתמש בשיטהsetRequiresBatteryNotLow()
שהוגדרה. - אחרי שמגדירים את
WorkRequest
, צריך להקצות את המשימה למערכת Android. כדי לעשות זאת, צריך לתזמן את המשימה באמצעות אחת מWorkManager
enqueue
השיטות הבאות. - הזמן המדויק שבו ה-
Worker
מופעל תלוי באילוצים שבהם נעשה שימוש ב-WorkRequest
ובאופטימיזציות של המערכת. האפליקציהWorkManager
נועדה לתת את ההתנהגות הטובה ביותר האפשרית, בכפוף להגבלות האלה.
קורס אוניברסיטה:
התיעוד של מפתח Android:
אחר:
בקטע הזה מפורטות מטלות שיעורי בית אפשריות לתלמידים שעובדים עם קוד Lab הזה, במסגרת קורס בהדרכת מורה. למורה יש אפשרות לבצע את הפעולות הבאות:
- אם צריך, מקצים שיעורי בית.
- ספרו לתלמידים איך מגישים מטלות בשיעורי בית.
- לתת ציונים למטלות שיעורי הבית.
המורים יכולים להשתמש בהצעות האלה כמה שפחות, ומומלץ להקצות להן כל שיעורי בית שדעתם מתאימה להם.
אם אתם עובדים בעצמכם על שיעור הקוד הזה, אתם מוזמנים להשתמש במטלות שיעורי הבית האלה כדי לבחון את הידע שלכם.
שאלה 1
איך הטמעת את הבטון של הכיתה WorkRequest
?
▬ OneTimeWorkPeriodicRequest
▢ OneTimeWorkRequest
ו-PeriodicWorkRequest
▢ OneTimeWorkRequest
ו-RecurringWorkRequest
▢ OneTimeOffWorkRequest
ו-RecurringWorkRequest
שאלה 2
באילו מהכיתות הבאות WorkManager
משתמש כדי לתזמן את משימת הרקע ב-API 23 ואילך?
הוספה של JobScheduler
בלבד
▢ BroadcastReceiver
ו-AlarmManager
▢ AlarmManager
ו-JobScheduler
▢ Scheduler
ו-BroadcastReceiver
שאלה 3
באיזה API את משתמשת כדי להוסיף אילוצים ל-WorkRequest
?
▬ setConstraints()
▬ addConstraints()
▬ setConstraint()
▬ addConstraintsToWorkRequest()
בשיעור הבא:
קישורים למעבדות אחרות של הקוד בקורס הזה זמינים בדף הנחיתה של Android Kotlin Fundamentals Codelabs.