Cette page présente les pratiques recommandées pour créer un widget plus avancé pour une meilleure expérience utilisateur.
Optimisations pour la mise à jour du contenu des widgets
La mise à jour du contenu d'un widget peut s'avérer coûteuse en calcul. Pour économiser la batterie la consommation, optimiser le type, la fréquence et la planification des mises à jour.
Types de mises à jour de widgets
Il existe trois façons de mettre à jour un widget: une mise à jour complète, une mise à jour partielle et, et, dans le cas d'un widget de collection, une actualisation des données. Chacun d'eux possède des les coûts de calcul et leurs ramifications.
Vous trouverez ci-dessous une description de chaque type de mise à jour et des extraits de code pour chacun d'eux.
Mise à jour complète:appelez
AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews)
pour mettre à jour complètement le widget. Il remplace les paramètresRemoteViews
par un nouveauRemoteViews
Il s'agit de la mise à jour la plus coûteuse en calcul.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);
Mise à jour partielle:appel
AppWidgetManager.partiallyUpdateAppWidget
pour mettre à jour certaines parties du widget. Cela fusionne le nouveauRemoteViews
avec le fourni précédemmentRemoteViews
. Cette méthode est ignorée si un widget ne reçoit pas au moins une mise à jour complète viaupdateAppWidget(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);
Actualisation des données de collection:appel
AppWidgetManager.notifyAppWidgetViewDataChanged
pour invalider les données d'une vue de collection dans votre widget. Cela déclencheRemoteViewsFactory.onDataSetChanged
En attendant, les anciennes données sont affichées dans le widget. Vous pouvez en toute sécurité effectuer des tâches coûteuses de manière synchrone avec cette méthode.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);
Vous pouvez appeler ces méthodes n'importe où dans votre application, à condition que celle-ci dispose de la
le même UID que celui
AppWidgetProvider
.
Déterminer la fréquence de mise à jour d'un widget
Les widgets sont mis à jour périodiquement en fonction de la valeur fournie pour le paramètre
updatePeriodMillis
. Le widget peut se mettre à jour en réponse à une interaction de l'utilisateur, une diffusion
mises à jour ou les deux.
Mettre à jour régulièrement
Vous pouvez contrôler la fréquence des mises à jour périodiques en spécifiant une valeur pour
AppWidgetProviderInfo.updatePeriodMillis
dans le fichier XML appwidget-provider
. Chaque
de mise à jour déclenche la méthode AppWidgetProvider.onUpdate()
, qui vous permet
vous pouvez placer le code pour mettre à jour le widget. Toutefois, considérez les alternatives pour
les mises à jour du broadcast receiver décrites dans un
dans la section suivante si votre widget doit charger des données de manière asynchrone ou
est supérieure à 10 secondes. En effet, au bout de 10 secondes, le système considère
BroadcastReceiver
pour ne pas répondre.
updatePeriodMillis
n'accepte pas les valeurs inférieures à 30 minutes. Toutefois, si
vous souhaitez désactiver les mises à jour périodiques, vous pouvez spécifier 0.
Vous pouvez autoriser les utilisateurs à ajuster la fréquence des mises à jour dans une configuration. Pour
Par exemple, il peut vouloir qu'un code boursier se mette à jour toutes les 15 minutes, soit toutes les quatre
fois par jour. Dans ce cas, définissez updatePeriodMillis
sur 0 et utilisez
WorkManager
à la place.
Mettre à jour en réponse à une interaction de l'utilisateur
Voici quelques recommandations pour mettre à jour le widget en fonction des interactions des utilisateurs:
Depuis une activité de l'application:appelez directement
AppWidgetManager.updateAppWidget
en réponse à une interaction de l'utilisateur, par exemple en appuyant sur l'écran.À partir d'interactions à distance, telles qu'une notification ou un widget d'application: construire un
PendingIntent
, puis mettre à jour le widget à partir de l'objet appeléActivity
,Broadcast
ouService
. Vous pouvez choisir votre propre priorité. Pour Par exemple, si vous sélectionnez un élémentBroadcast
pourPendingIntent
, vous pouvez choisir une diffusion de premier plan pour donnerBroadcastReceiver
.
Mettre à jour en réponse à un événement de diffusion
Voici un exemple d'événement de diffusion nécessitant la mise à jour d'un widget : l'utilisateur prend une photo. Dans ce cas, vous souhaitez mettre à jour le widget lorsqu'une nouvelle photo est détecté.
Vous pouvez planifier une tâche avec JobScheduler
et spécifier une diffusion en tant que
à l'aide de la méthode
JobInfo.Builder.addTriggerContentUri
.
Vous pouvez également enregistrer un BroadcastReceiver
pour la diffusion, par exemple :
écoute de
ACTION_LOCALE_CHANGED
Toutefois, comme cette méthode consomme des ressources de l'appareil, utilisez-la avec précaution
pour une diffusion spécifique. Avec le lancement de la diffusion
Limites sous Android
7.0 (niveau d'API 24) et Android 8.0 (niveau d'API 26), les applications ne peuvent pas enregistrer de données implicites
dans leurs fichiers manifestes, avec certaines
exceptions.
Éléments à prendre en compte lors de la mise à jour d'un widget à partir d'un BroadcastReceiver
Si le widget est mis à jour à partir d'une BroadcastReceiver
, y compris
AppWidgetProvider
, tenez compte des points suivants concernant le
la durée et la priorité
d'une mise à jour de widget.
Durée de la mise à jour
En règle générale, le système autorise les broadcast receivers, qui s'exécutent généralement dans le thread principal, s'exécuter pendant 10 secondes maximum avant de considérer qu'elles ne répondent pas et déclencher une alerte Application Réponse (ANR). S’il faut plus de temps pour mettez à jour le widget, envisagez les alternatives suivantes:
Planifiez une tâche à l'aide de
WorkManager
.Donnez plus de temps au destinataire
goAsync
. Cela permet aux récepteurs de s'exécuter pendant 30 secondes.
Reportez-vous à la section Considérations de sécurité et meilleures pratiques pour en savoir plus des informations.
Priorité de la mise à jour
Par défaut, les annonces, y compris celles effectuées avec
AppWidgetProvider.onUpdate
: s'exécute en tant que processus en arrière-plan. Cela signifie
des ressources système surchargées peuvent entraîner un retard dans l'appel de la diffusion
destinataire. Pour donner la priorité à la diffusion, faites-en un processus de premier plan.
Par exemple, ajoutez le paramètre
Intent.FLAG_RECEIVER_FOREGROUND
pour Intent
transmis à PendingIntent.getBroadcast
lorsque l'utilisateur
appuie sur une certaine
partie du widget.
Créer des aperçus précis qui incluent des éléments dynamiques
<ph type="x-smartling-placeholder">Cette section explique l'approche recommandée pour afficher plusieurs éléments dans
un aperçu d'un widget comportant une collection
vue, c'est-à-dire un widget qui utilise
ListView
, GridView
ou StackView
.
Si votre widget utilise l'une de ces vues, vous pouvez créer un aperçu évolutif directement en fournissant le widget dégrade la mise en page lorsque l'aperçu du widget n'affiche aucun élément. Cela se produit parce que les données de la vue "Collection" sont définies de manière dynamique au moment de l'exécution et ressemblent à comme illustré dans la figure 1.
Pour que les aperçus des widgets avec des vues de collection s'affichent correctement dans le widget
nous vous recommandons de conserver un fichier de mise en page distinct, dédié uniquement
un aperçu. Ce fichier de mise en page distinct inclut la disposition réelle du widget et une
la vue de collection d’espace réservé avec des articles factices. Par exemple, vous pouvez imiter
ListView
en fournissant un espace réservé LinearLayout
avec plusieurs fausses listes
éléments.
Pour illustrer un exemple de ListView
, commencez avec un fichier de mise en page distinct:
// res/layout/widget_preview.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/widget_background"
android:orientation="vertical">
// Include the actual widget layout that contains ListView.
<include
layout="@layout/widget_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
// The number of fake items you include depends on the values you provide
// for minHeight or targetCellHeight in the AppWidgetProviderInfo
// definition.
<TextView android:text="@string/fake_item1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="?attr/appWidgetInternalPadding" />
<TextView android:text="@string/fake_item2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="?attr/appWidgetInternalPadding" />
</LinearLayout>
Spécifiez le fichier de mise en page d'aperçu lorsque vous fournissez l'attribut previewLayout
de
les métadonnées AppWidgetProviderInfo
. Vous devez toujours spécifier la mise en page réelle du widget.
pour l'attribut initialLayout
et utilisez la mise en page réelle du widget lorsque
en créant un RemoteViews
au moment de l'exécution.
<appwidget-provider
previewLayout="@layout/widget_previe"
initialLayout="@layout/widget_view" />
Éléments de liste complexes
L'exemple de la section précédente fournit de faux éléments de liste, car la liste
Les éléments sont des objets TextView
. Il peut s'agir
plus complexe pour fournir de faux éléments
si les éléments sont des mises en page complexes.
Prenons l'exemple d'un élément de liste défini dans widget_list_item.xml
et composé des éléments suivants :
deux objets TextView
:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView android:id="@id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/fake_title" />
<TextView android:id="@id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/fake_content" />
</LinearLayout>
Pour fournir de faux éléments de liste, vous pouvez inclure la mise en page plusieurs fois, mais cela chaque élément de la liste est identique. Pour fournir des éléments de liste uniques, procédez comme suit : procédez comme suit:
Créez un ensemble d'attributs pour les valeurs textuelles:
<resources> <attr name="widgetTitle" format="string" /> <attr name="widgetContent" format="string" /> </resources>
Utilisez les attributs suivants pour définir le texte:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="?widgetTitle" /> <TextView android:id="@id/content" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="?widgetContent" /> </LinearLayout>
Créez autant de styles que nécessaire pour l'aperçu. Redéfinissez les valeurs dans chaque style:
<resources> <style name="Theme.Widget.ListItem"> <item name="widgetTitle"></item> <item name="widgetContent"></item> </style> <style name="Theme.Widget.ListItem.Preview1"> <item name="widgetTitle">Fake Title 1</item> <item name="widgetContent">Fake content 1</item> </style> <style name="Theme.Widget.ListItem.Preview2"> <item name="widgetTitle">Fake title 2</item> <item name="widgetContent">Fake content 2</item> </style> </resources>
Appliquez les styles aux éléments factices dans la mise en page d'aperçu:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" ...> <include layout="@layout/widget_view" ... /> <include layout="@layout/widget_list_item" android:theme="@style/Theme.Widget.ListItem.Preview1" /> <include layout="@layout/widget_list_item" android:theme="@style/Theme.Widget.ListItem.Preview2" /> </LinearLayout>