בדף הזה מוסברות שיטות מומלצות ליצירת ווידג'ט מתקדם יותר כדי לשפר את חוויית המשתמש.
אופטימיזציות לעדכון תוכן הווידג'ט
עדכון תוכן הווידג'ט יכול להיות יקר מבחינת משאבי מחשוב. כדי לחסוך בצריכת הסוללה, כדאי לבצע אופטימיזציה של סוג העדכון, התדירות והתזמון.
סוגי עדכונים לווידג'טים
יש שלוש דרכים לעדכן ווידג'ט: עדכון מלא, עדכון חלקי ורענון נתונים (במקרה של ווידג'ט אוסף). לכל אחד מהם יש עלויות חישוב והשלכות שונות.
בהמשך מפורט כל סוג עדכון, ומוצגים קטעי קוד לכל סוג.
עדכון מלא: מתקשרים אל
AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews)
כדי לעדכן את הווידג'ט באופן מלא. הפעולה הזו תחליף אתRemoteViews
שסופק קודם ב-RemoteViews
חדש. זהו העדכון הכי יקר מבחינת משאבי מחשוב.Kotlin
val appWidgetManager = AppWidgetManager.getInstance(context) val remoteViews = RemoteViews(context.getPackageName(), R.layout.widgetlayout).also { setTextViewText(R.id.textview_widget_layout1, "Updated text1") setTextViewText(R.id.textview_widget_layout2, "Updated text2") } appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
Java
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout); remoteViews.setTextViewText(R.id.textview_widget_layout1, "Updated text1"); remoteViews.setTextViewText(R.id.textview_widget_layout2, "Updated text2"); appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
עדכון חלקי: קוראים ל-
AppWidgetManager.partiallyUpdateAppWidget
כדי לעדכן חלקים בווידג'ט. הפעולה הזו תמזג אתRemoteViews
החדש עםRemoteViews
שסופק קודם. המערכת מתעלמת מהשיטה הזו אם הווידג'ט לא מקבל לפחות עדכון מלא אחד דרךupdateAppWidget(int[], RemoteViews)
.Kotlin
val appWidgetManager = AppWidgetManager.getInstance(context) val remoteViews = RemoteViews(context.getPackageName(), R.layout.widgetlayout).also { setTextViewText(R.id.textview_widget_layout, "Updated text") } appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteViews)
Java
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout); remoteViews.setTextViewText(R.id.textview_widget_layout, "Updated text"); appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteViews);
רענון נתוני האוסף: קריאה ל-
AppWidgetManager.notifyAppWidgetViewDataChanged
כדי לבטל את תוקף הנתונים של תצוגת אוסף בווידג'ט. הפעולה הזו מפעילה אתRemoteViewsFactory.onDataSetChanged
. בינתיים, הנתונים הישנים מוצגים בווידג'ט. באמצעות השיטה הזו אפשר לבצע משימות יקרות באופן סינכרוני בצורה בטוחה.Kotlin
val appWidgetManager = AppWidgetManager.getInstance(context) appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview)
Java
AppWidgetManager 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
.
עדכון בתגובה לאירוע שידור
דוגמה לאירוע שידור שדורש עדכון של הווידג'ט היא כשמשתמש מצלם תמונה. במקרה הזה, רוצים לעדכן את הווידג'ט כשמזוהה תמונה חדשה.
אפשר לתזמן עבודה עם JobScheduler
ולציין שידור כטריגר באמצעות השיטה JobInfo.Builder.addTriggerContentUri
.
אפשר גם להירשם לשידור – לדוגמה, להירשם להאזנה לACTION_LOCALE_CHANGED
.BroadcastReceiver
עם זאת, מכיוון שהפעולה הזו צורכת משאבי מכשיר, צריך להשתמש בה בזהירות ולהאזין רק לשידור הספציפי. עם ההשקה של מגבלות על שידורים ב-Android 7.0 (רמת API 24) וב-Android 8.0 (רמת API 26), אפליקציות לא יכולות לרשום שידורים מרומזים במניפסטים שלהן, עם חריגים מסוימים.
שיקולים כשמעדכנים ווידג'ט מ-BroadcastReceiver
אם הווידג'ט מתעדכן מ-BroadcastReceiver
, כולל AppWidgetProvider
, חשוב לשים לב לשיקולים הבאים לגבי משך הזמן והעדיפות של עדכון הווידג'ט.
משך העדכון
ככלל, המערכת מאפשרת ל-broadcast receivers, שפועלים בדרך כלל בשרשור הראשי של האפליקציה, לפעול עד 10 שניות לפני שהיא מחשיבה אותם כלא מגיבים ומפעילה שגיאת Application Not Responding (ANR). כדי להימנע מחסימה של ה-main thread בזמן הטיפול בשידור, משתמשים בשיטה 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
כשהמשתמש מקיש על חלק מסוים בווידג'ט.