Questa pagina spiega le pratiche consigliate per la creazione di un widget più avanzato per una migliore esperienza utente.
Ottimizzazioni per l'aggiornamento dei contenuti dei widget
L'aggiornamento dei contenuti dei widget può essere costoso dal punto di vista computazionale. Per risparmiare il consumo della batteria, ottimizza il tipo, la frequenza e la tempistica dell'aggiornamento.
Tipi di aggiornamenti dei widget
Esistono tre modi per aggiornare un widget: un aggiornamento completo, un aggiornamento parziale e, nel caso di un widget di raccolta, un aggiornamento dei dati. Ognuno ha costi computazionali e ramificazioni diversi.
Di seguito viene descritto ogni tipo di aggiornamento e vengono forniti snippet di codice per ciascuno.
Aggiornamento completo: chiama
AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews)per aggiornare completamente il widget. In questo modo, ilRemoteViewsfornito in precedenza viene sostituito con un nuovoRemoteViews. Questo è l'aggiornamento più costoso dal punto di vista computazionale.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);
Aggiornamento parziale: chiama
AppWidgetManager.partiallyUpdateAppWidgetper aggiornare parti del widget. In questo modo, il nuovoRemoteViewsviene unito alRemoteViewsfornito in precedenza. Questo metodo viene ignorato se un widget non riceve almeno un aggiornamento completo tramiteupdateAppWidget(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);
Aggiornamento dei dati della raccolta: chiama
AppWidgetManager.notifyAppWidgetViewDataChangedper invalidare i dati di una visualizzazione della raccolta nel widget. In questo modo viene attivatoRemoteViewsFactory.onDataSetChanged. Nel frattempo, nel widget vengono visualizzati i vecchi dati. Puoi eseguire in modo sicuro attività costose in modo sincrono con questo metodo.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);
Puoi chiamare questi metodi da qualsiasi punto dell'app, a condizione che l'app abbia lo stesso UID della classe corrispondente.AppWidgetProvider
Determinare la frequenza di aggiornamento di un widget
I widget vengono aggiornati periodicamente in base al valore fornito per l'
updatePeriodMillis
attributo. Il widget può essere aggiornato in risposta all'interazione dell'utente, agli aggiornamenti delle trasmissioni o a entrambi.
Aggiornare periodicamente
Puoi controllare la frequenza dell'aggiornamento periodico specificando un valore per AppWidgetProviderInfo.updatePeriodMillis nel file XML appwidget-provider. Ogni aggiornamento attiva il metodo AppWidgetProvider.onUpdate(), in cui puoi inserire il codice per aggiornare il widget. Tuttavia, se il widget deve caricare i dati in modo asincrono o impiega più
di 10 secondi per l'aggiornamento, valuta le alternative per
gli aggiornamenti dei broadcast receiver descritte in una
sezione successiva, perché dopo 10 secondi il sistema considera un
BroadcastReceiver come non reattivo.
updatePeriodMillis non supporta valori inferiori a 30 minuti. Tuttavia, se vuoi disattivare gli aggiornamenti periodici, puoi specificare 0.
Puoi consentire agli utenti di modificare la frequenza degli aggiornamenti in una configurazione. Ad esempio, potrebbero voler aggiornare un ticker azionario ogni 15 minuti o solo quattro volte al giorno. In questo caso, imposta updatePeriodMillis su 0 e utilizza
WorkManager invece.
Aggiornare in risposta a un'interazione dell'utente
Ecco alcuni modi consigliati per aggiornare il widget in base all'interazione dell'utente:
Da un'attività dell'app: chiama direttamente
AppWidgetManager.updateAppWidgetin risposta a un'interazione dell'utente, ad esempio un tocco dell'utente.Da interazioni remote, ad esempio una notifica o un widget dell'app: crea un
PendingIntent, quindi aggiorna il widget dall'Activity, dallaBroadcasto dalServicerichiamato. Puoi scegliere la tua priorità. Ad esempio, se selezioni unBroadcastperPendingIntent, puoi scegliere una trasmissione in primo piano per dare laBroadcastReceiverpriorità.
Aggiornare in risposta a un evento di trasmissione
Un esempio di evento di trasmissione che richiede l'aggiornamento di un widget è quando l'utente scatta una foto. In questo caso, devi aggiornare il widget quando viene rilevata una nuova foto.
Puoi pianificare un job con JobScheduler e specificare una trasmissione come
trigger utilizzando il
JobInfo.Builder.addTriggerContentUri
metodo.
Puoi anche registrare un BroadcastReceiver per la trasmissione, ad esempio,
ascoltando
ACTION_LOCALE_CHANGED.
Tuttavia, poiché questa operazione consuma le risorse del dispositivo, utilizzala con cautela e ascolta solo la trasmissione specifica. Con l'introduzione delle limitazioni delle trasmissioni in Android 7.0 (livello API 24) e Android 8.0 (livello API 26), le app non possono registrare trasmissioni implicite nei relativi manifest, con alcune eccezioni.
Considerazioni sull'aggiornamento di un widget da un BroadcastReceiver
Se il widget viene aggiornato da un BroadcastReceiver, incluso AppWidgetProvider, tieni presente le seguenti considerazioni relative alla durata e alla priorità di un aggiornamento del widget.
Durata dell'aggiornamento
In genere, il sistema consente ai ricevitori di trasmissione, che in genere vengono eseguiti nel thread principale dell'app, di essere eseguiti per un massimo di 10 secondi prima di considerarli non reattivi e
di attivare un errore di tipo "L'applicazione non
risponde" (ANR). Per evitare di bloccare il
thread principale durante la gestione della trasmissione, utilizza il
goAsync metodo. Se l'aggiornamento del widget richiede più tempo, valuta la possibilità di pianificare un'attività
utilizzando WorkManager.
Caution: Any work you do here blocks further broadcasts until it completes,
so it can slow the receiving of later events.
Per ulteriori informazioni, consulta Considerazioni e best practice per la sicurezza.
Priorità dell'aggiornamento
Per impostazione predefinita, le trasmissioni, incluse quelle effettuate utilizzando AppWidgetProvider.onUpdate, vengono eseguite come processi in background. Ciò significa che le risorse di sistema sovraccariche possono causare un ritardo nella chiamata del ricevitore di trasmissione. Per dare la priorità alla trasmissione, trasformala in un processo in primo piano.
Ad esempio, aggiungi il
Intent.FLAG_RECEIVER_FOREGROUND
flag al Intent passato a PendingIntent.getBroadcast quando l'utente
tocca una determinata parte del widget.