יצירת ווידג'ט מתקדם

כדאי לנסות את הדרך של Compose
‫Jetpack Compose היא ערכת הכלים המומלצת לבניית ממשק משתמש ל-Android. איך יוצרים ווידג'טים באמצעות ממשקי API בסגנון Compose

בדף הזה מוסברות שיטות מומלצות ליצירת ווידג'ט מתקדם יותר כדי לשפר את חוויית המשתמש.

אופטימיזציות לעדכון תוכן הווידג'ט

עדכון תוכן הווידג'ט יכול להיות יקר מבחינת משאבי מחשוב. כדי לחסוך בצריכת הסוללה, כדאי לבצע אופטימיזציה של סוג העדכון, התדירות והתזמון.

סוגי עדכונים לווידג'טים

יש שלוש דרכים לעדכן ווידג'ט: עדכון מלא, עדכון חלקי ורענון נתונים (במקרה של ווידג'ט אוסף). לכל אחד מהם יש עלויות חישוב והשלכות שונות.

בהמשך מפורט כל סוג עדכון, ומוצגים קטעי קוד לכל סוג.

val appWidgetManager = AppWidgetManager.getInstance(context)
val remoteViews = RemoteViews(context.packageName, R.layout.widgetlayout).apply {
    setTextViewText(R.id.textview_widget_layout1, "Updated text1")
    setTextViewText(R.id.textview_widget_layout2, "Updated text2")
}
appWidgetManager.updateAppWidget(appWidgetId, remoteViews)

val appWidgetManager = AppWidgetManager.getInstance(context)
val remoteViews = RemoteViews(context.packageName, R.layout.widgetlayout).apply {
    setTextViewText(R.id.textview_widget_layout, "Updated text")
}
appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteViews)

  • רענון נתוני האוסף: קוראים ל-call AppWidgetManager.notifyAppWidgetViewDataChanged כדי לבטל את תוקף הנתונים של תצוגת אוסף בווידג'ט. הפעולה הזו מפעילה את RemoteViewsFactory.onDataSetChanged. בינתיים, הנתונים הישנים מוצגים בווידג'ט. באמצעות השיטה הזו אפשר לבצע משימות יקרות באופן סינכרוני בצורה בטוחה.

val appWidgetManager = AppWidgetManager.getInstance(context)
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview)

אפשר להפעיל את השיטות האלה מכל מקום באפליקציה, כל עוד לאפליקציה יש את אותו UID כמו למחלקה התואמת AppWidgetProvider.

קביעת התדירות של עדכון הווידג'ט

הווידג'טים מתעדכנים מעת לעת בהתאם לערך שצוין במאפיין updatePeriodMillis. הווידג'ט יכול להתעדכן בתגובה לאינטראקציה של המשתמש, לשדר עדכונים או לבצע את שתי הפעולות.

עדכון תקופתי

כדי לשלוט בתדירות העדכון התקופתי, מציינים ערך לפרמטר AppWidgetProviderInfo.updatePeriodMillis בקובץ ה-XML של appwidget-provider. כל עדכון מפעיל את השיטה AppWidgetProvider.onUpdate(), שבה אפשר להציב את הקוד לעדכון הווידג'ט. עם זאת, אם הווידג'ט צריך לטעון נתונים באופן אסינכרוני או שלוקח לו יותר מ-10 שניות להתעדכן, כדאי לשקול את החלופות לעדכונים של מקלטי שידור שמתוארות בקטע הבא, כי אחרי 10 שניות המערכת מחשיבה את BroadcastReceiver כלא מגיב.

המאפיין updatePeriodMillis לא תומך בערכים של פחות מ-30 דקות. עם זאת, אם רוצים להשבית את העדכונים התקופתיים, אפשר לציין 0.

אתם יכולים לאפשר למשתמשים לשנות את תדירות העדכונים בהגדרה. לדוגמה, הם יכולים לרצות שהעדכון של נתוני מניות יתבצע כל 15 דקות או רק ארבע פעמים ביום. במקרה כזה, צריך להגדיר את updatePeriodMillis ל-0 ולהשתמש ב-WorkManager.

עדכון בתגובה לאינטראקציה של משתמש

ריכזנו כאן כמה דרכים מומלצות לעדכן את הווידג'ט על סמך אינטראקציה של המשתמשים:

  • מפעילות של האפליקציה: קריאה ישירה ל-AppWidgetManager.updateAppWidget בתגובה לאינטראקציה של משתמש, כמו הקשה של משתמש.

  • מאינטראקציות מרחוק, כמו התראה או ווידג'ט של אפליקציה: יוצרים PendingIntent, ואז מעדכנים את הווידג'ט מה-Activity,‏ Broadcast או Service שהופעלו. אתם יכולים לבחור את העדיפות שלכם. לדוגמה, אם בוחרים Broadcast בשביל PendingIntent, אפשר לבחור שידור בחזית כדי לתת עדיפות לBroadcastReceiver.

עדכון בתגובה לאירוע שידור

דוגמה לאירוע שידור שדורש עדכון של הווידג'ט היא כשמשתמש מצלם תמונה. במקרה הזה, רוצים לעדכן את הווידג'ט כשמזוהה תמונה חדשה.

אפשר לתזמן עבודה עם WorkManager ולציין טריגר של URI של תוכן באמצעות השיטה Constraints.Builder.addContentUriTrigger.

אפשר גם להירשם לBroadcastReceiverשידור – לדוגמה, להאזין לACTION_LOCALE_CHANGED. עם זאת, מכיוון שהפעולה הזו צורכת משאבי מכשיר, חשוב להשתמש בה בזהירות ולהאזין רק לשידור הספציפי. עם השקת מגבלות על שידורים ב-Android 7.0 (רמת API‏ 24) וב-Android 8.0 (רמת API‏ 26), אפליקציות לא יכולות לרשום שידורים מרומזים במניפסטים שלהן, עם חריגים מסוימים.

שיקולים כשמעדכנים ווידג'ט מ-BroadcastReceiver

אם הווידג'ט מתעדכן מ-BroadcastReceiver, כולל AppWidgetProvider, חשוב לשים לב לשיקולים הבאים לגבי משך הזמן והעדיפות של עדכון הווידג'ט.

משך העדכון

ככלל, המערכת מאפשרת ל-broadcast receivers, שפועלים בדרך כלל ב-main thread של האפליקציה, לפעול עד 10 שניות לפני שהיא מחשיבה אותם כלא מגיבים ומפעילה שגיאת Application Not Responding (ANR). כדי להימנע מחסימת השרשור הראשי בזמן הטיפול בשידור, משתמשים בשיטה goAsync. אם העדכון של הווידג'ט נמשך זמן רב, כדאי לתזמן משימה באמצעות WorkManager.

Caution: Any work you do here blocks further broadcasts until it completes,
so it can slow the receiving of later events.

מידע נוסף זמין במאמר בנושא שיקולי אבטחה ושיטות מומלצות.

העדיפות של העדכון

כברירת מחדל, שידורים – כולל שידורים שמתבצעים באמצעות AppWidgetProvider.onUpdate – פועלים כתהליכי רקע. המשמעות היא שמשאבי מערכת עמוסים מדי עלולים לגרום לעיכוב בהפעלת מקלט השידור. כדי לתת עדיפות לשידור, צריך להגדיר אותו כתהליך בחזית.

לדוגמה, אפשר להוסיף את הדגל Intent.FLAG_RECEIVER_FOREGROUND ל-Intent שמועבר אל PendingIntent.getBroadcast כשמשתמש מקיש על חלק מסוים בווידג'ט.