本頁說明建立進階小工具的建議做法,協助您提供更優質的使用者體驗。
更新小工具內容的最佳化
更新小工具內容可能會耗費大量運算資源。如要節省電池用量,請最佳化更新類型、頻率和時間。
小工具更新類型
更新小工具的方式有三種:完整更新、部分更新,以及集合小工具的資料重新整理。每種方法都有不同的運算成本和影響。
以下說明各個更新類型,並提供程式碼片段。
- 完整更新:呼叫
AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews)即可完整更新小工具。這會將先前提供的RemoteViews替換為新的RemoteViews。這是運算成本最高的更新。
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)
部分更新:呼叫
AppWidgetManager.partiallyUpdateAppWidget,更新小工具的部分內容。這會將新的RemoteViews與先前提供的RemoteViews合併。如果小工具未透過updateAppWidget(int[], 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)
- 集合資料重新整理:呼叫
AppWidgetManager.notifyAppWidgetViewDataChanged,使小工具中集合檢視畫面的資料失效。這會觸發RemoteViewsFactory.onDataSetChanged。在此期間,小工具會顯示舊資料。您可以使用這個方法,安全地同步執行耗費資源的工作。
val appWidgetManager = AppWidgetManager.getInstance(context) appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview)
只要應用程式的 UID 與對應的 AppWidgetProvider 類別相同,您就可以從應用程式中的任何位置呼叫這些方法。
決定小工具的更新頻率
小工具會根據為 updatePeriodMillis 屬性提供的值定期更新。小工具可以根據使用者互動、廣播更新或兩者進行更新。
定期更新
您可以在 appwidget-provider XML 中指定 AppWidgetProviderInfo.updatePeriodMillis 的值,控制定期更新的頻率。每次更新都會觸發 AppWidgetProvider.onUpdate() 方法,您可以在其中放置更新小工具的程式碼。不過,如果小工具需要以非同步方式載入資料,或需要超過 10 秒才能更新,請考慮採用下節所述的廣播接收器更新替代方案,因為超過 10 秒後,系統會將 BroadcastReceiver 視為無回應。
updatePeriodMillis 不支援小於 30 分鐘的值。不過,如要停用定期更新,可以指定 0。
您可以讓使用者調整設定中的更新頻率。舉例來說,他們可能希望股票代碼每 15 分鐘更新一次,或每天只更新四次。在這種情況下,請將 updatePeriodMillis 設為 0,並改用 WorkManager。
因應使用者互動更新
以下是根據使用者互動更新小工具的建議做法:
從應用程式的活動:直接呼叫
AppWidgetManager.updateAppWidget,以回應使用者互動,例如使用者輕觸。透過遠端互動 (例如通知或應用程式小工具):建構
PendingIntent,然後從叫用的Activity、Broadcast或Service更新小工具。您可以自行選擇優先順序。舉例來說,如果您為PendingIntent選取Broadcast,可以選擇「前景廣播」,優先處理BroadcastReceiver。
因應廣播事件進行更新
舉例來說,使用者拍照時,系統會觸發廣播事件,要求小工具更新。在這種情況下,您需要在偵測到新相片時更新小工具。
您可以使用 WorkManager 排定工作,並使用 Constraints.Builder.addContentUriTrigger 方法指定內容 URI 觸發條件。
您也可以為廣播註冊 BroadcastReceiver,例如監聽 ACTION_LOCALE_CHANGED。不過,由於這會耗用裝置資源,請謹慎使用,並僅監聽特定廣播。Android 7.0 (API 級別 24) 和 Android 8.0 (API 級別 26) 推出廣播限制後,應用程式無法在資訊清單中註冊隱式廣播,但有部分例外狀況。
從 BroadcastReceiver 更新小工具的注意事項
如果小工具是透過 BroadcastReceiver (包括 AppWidgetProvider) 更新,請留意下列有關小工具更新時間長度和優先順序的注意事項。
更新時間長度
一般來說,系統會讓廣播接收器 (通常在應用程式的主執行緒中執行) 執行最多 10 秒,然後才會將其視為無回應,並觸發應用程式無回應 (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 旗標新增至傳遞至 PendingIntent.getBroadcast 的 Intent。