Erweitertes Widget erstellen

Auf dieser Seite werden empfohlene Vorgehensweisen zum Erstellen eines erweiterten Widgets für User Experience zu verbessern.

Optimierungen für die Aktualisierung von Widget-Inhalten

Das Aktualisieren von Widget-Inhalten kann rechenintensiv sein. Um den Akku zu schonen Aktualisierungsart, -häufigkeit und -zeitpunkt optimieren.

Arten von Widget-Updates

Es gibt drei Möglichkeiten, ein Widget zu aktualisieren: eine vollständige Aktualisierung, eine teilweise Aktualisierung und im Fall eines Sammlungs-Widgets eine Datenaktualisierung. Jedes hat unterschiedliche Computing-Kosten und Auswirkungen.

Im Folgenden werden die einzelnen Aktualisierungstypen beschrieben und Code-Snippets für jeden Typ bereitgestellt.

  • Vollständige Aktualisierung:AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews) anrufen um das Widget vollständig zu aktualisieren. Dies ersetzt das zuvor bereitgestellte RemoteViews mit einem neuen RemoteViews. Dies ist das rechenintensivste Update.

    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);
    
  • Teilweise Aktualisierung: Anruf AppWidgetManager.partiallyUpdateAppWidget um Teile des Widgets zu aktualisieren. Dadurch werden die neuen RemoteViews und die Zuvor bereitgestelltes RemoteViews. Diese Methode wird ignoriert, wenn ein Widget erhält nicht mindestens ein vollständiges Update bis 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);
    
  • Aktualisierung der Sammlungsdaten: Aufruf AppWidgetManager.notifyAppWidgetViewDataChanged um die Daten einer Sammlungsansicht in Ihrem Widget ungültig zu machen. Dadurch wird ausgelöst, RemoteViewsFactory.onDataSetChanged In der Zwischenzeit werden die alten Daten im Widget angezeigt. Sie können synchrone Ausführung teurer Aufgaben mit dieser Methode.

    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);
    

Sie können diese Methoden von überall in Ihrer App aufrufen, solange die App über die wie die entsprechende Klasse AppWidgetProvider.

Bestimmen, wie oft ein Widget aktualisiert werden soll

Widgets werden regelmäßig aktualisiert, je nachdem, welchen Wert für den updatePeriodMillis . Das Widget kann als Reaktion auf Nutzerinteraktion, Broadcast- Updates oder beides.

Regelmäßig aktualisieren

Sie können die Häufigkeit der regelmäßigen Updates festlegen, indem Sie einen Wert für AppWidgetProviderInfo.updatePeriodMillis in der XML-Datei appwidget-provider. Jedes "update" löst die Methode AppWidgetProvider.onUpdate() aus, mit der Sie den Code zum Aktualisieren des Widgets platzieren kann. Ziehen Sie jedoch die Alternativen für Updates zu Übertragungsempfängern wenn Ihr Widget Daten asynchron laden muss oder als 10 Sekunden für die Aktualisierung, da das System nach 10 Sekunden BroadcastReceiver reagiert nicht.

updatePeriodMillis unterstützt keine Werte unter 30 Minuten. Wenn jedoch Sie regelmäßige Updates deaktivieren möchten, können Sie 0 angeben.

Sie können Nutzern erlauben, die Häufigkeit von Aktualisierungen in einer Konfiguration anzupassen. Für Sie möchten vielleicht, dass ein Börsenticker alle 15 Minuten oder nur 4 Minuten aktualisiert wird. -mal pro Tag. Setzen Sie in diesem Fall updatePeriodMillis auf 0 und verwenden Sie WorkManager.

Aktualisierung als Reaktion auf eine Nutzerinteraktion

Hier sind einige empfohlene Möglichkeiten, das Widget basierend auf der Nutzerinteraktion zu aktualisieren:

  • Über eine Aktivität der App:direkt anrufen AppWidgetManager.updateAppWidget als Reaktion auf eine Nutzerinteraktion, z. B. wie beim Tippen der Nutzenden.

  • Über Remote-Interaktionen wie Benachrichtigungen oder App-Widgets: Erstellen Sie ein PendingIntent und aktualisieren Sie dann das Widget über die aufgerufene Activity, Broadcast oder Service. Sie können Ihre eigene Priorität festlegen. Für Wenn Sie beispielsweise einen Broadcast für PendingIntent auswählen, können Sie eine Übertragung im Vordergrund, um Priorität BroadcastReceiver.

Aktualisierung als Reaktion auf eine Übertragung

Ein Beispiel für ein Übertragungsereignis, für das ein Widget aktualisiert werden muss, ist der Zeitpunkt, der Nutzer ein Foto aufnimmt. In diesem Fall möchten Sie das Widget aktualisieren, wenn ein neues Foto erkannt wird.

Sie können einen Job mit JobScheduler planen und eine Übertragung als die mit der Methode JobInfo.Builder.addTriggerContentUri .

Sie können auch ein BroadcastReceiver für die Übertragung registrieren, z. B.: zuhören auf ACTION_LOCALE_CHANGED Da dies jedoch Geräteressourcen verbraucht, solltest du es vorsichtig verwenden und hören. nur auf die jeweilige Übertragung. Mit der Einführung der Einschränkungen bei Android 7.0 (API-Level 24) und Android 8.0 (API-Level 26) können Apps nicht implizit registriert werden. in ihren Manifesten übertragen, wobei bestimmte Ausnahmen.

Überlegungen zur Aktualisierung eines Widgets von einem BroadcastReceiver

Wenn das Widget über eine BroadcastReceiver aktualisiert wird, einschließlich AppWidgetProvider, beachten Sie die folgenden Hinweise zum Dauer und Priorität eines Widget-Updates.

Dauer der Aktualisierung

In der Regel lässt das System Übertragungsempfänger, die normalerweise im bis zu 10 Sekunden laufen, bevor sie als nicht reagierend das Auslösen einer Nicht-App- Antwortfehler (ANR) Wenn es länger dauert, das Widget aktualisieren möchten, haben Sie folgende Alternativen:

  • Planen Sie eine Aufgabe mit WorkManager.

  • Geben Sie dem Empfänger mehr Zeit mit dem goAsync-Methode. Dadurch wird die Ausführung durch Empfänger 30 Sekunden lang ermöglicht.

Siehe Sicherheitsaspekte und Best Practices finden Sie weitere Informationen.

Priorität des Updates

Standardmäßig werden Übertragungen – einschließlich solcher, die per AppWidgetProvider.onUpdate – als Hintergrundprozesse ausführen Das bedeutet, Überlastete Systemressourcen können zu einer Verzögerung beim Aufruf der Übertragung führen. Empfänger. Wenn du die Übertragung priorisieren möchtest, solltest du sie als Vordergrundprozess festlegen.

Fügen Sie beispielsweise den Parameter Intent.FLAG_RECEIVER_FOREGROUND an die Intent übergeben, die an PendingIntent.getBroadcast übergeben wird, wenn der Nutzer auf einen bestimmten Teil des Widgets tippt.

Genaue Vorschauen erstellen, die dynamische Elemente enthalten

<ph type="x-smartling-placeholder">
</ph>
Abbildung 1 : Widget-Vorschau ohne Listenelemente

In diesem Abschnitt wird die empfohlene Vorgehensweise für die Anzeige mehrerer Elemente in Widget-Vorschau für ein Widget mit einer Sammlung -Ansicht, d. h. ein Widget, das ListView, GridView oder StackView.

Wenn Ihr Widget eine dieser Ansichten verwendet, können Sie durch die direkte Erstellung einer skalierbaren Vorschau das Widget selbst zur Verfügung stellt. Layout verschlechtert wenn in der Widget-Vorschau keine Elemente angezeigt werden. Das liegt daran, Die Daten der Sammlungsansicht werden zur Laufzeit dynamisch festgelegt und ähneln den wie in Abbildung 1 dargestellt.

Damit eine Vorschau von Widgets mit Sammlungsansichten ordnungsgemäß im Widget angezeigt wird -Auswahl empfehlen wir, eine separate Layoutdatei zu erstellen, die nur für den in der Vorschau ansehen. Diese separate Layoutdatei enthält das Widget-Layout und ein Ansicht einer Platzhaltersammlung mit gefälschten Elementen. Sie können beispielsweise eine ListView durch Angabe des Platzhalters LinearLayout mit mehreren gefälschten Listen Elemente.

Um ein Beispiel für ein ListView zu veranschaulichen, beginnen Sie mit einer separaten Layoutdatei:

// 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>

Geben Sie die Vorschau-Layoutdatei an, wenn Sie das Attribut previewLayout von die AppWidgetProviderInfo-Metadaten. Sie legen dennoch das Layout des Widgets fest. für das Attribut initialLayout und verwenden Sie das tatsächliche Widget-Layout, wenn RemoteViews zur Laufzeit erstellen.

<appwidget-provider
    previewLayout="@layout/widget_previe"
    initialLayout="@layout/widget_view" />

Komplexe Listenelemente

Das Beispiel im vorherigen Abschnitt enthält gefälschte Listenelemente, da die Liste Elemente sind TextView-Objekte. Es kann sein, komplexere Layouts vor, um gefälschte Elemente bereitzustellen.

Nehmen wir ein Listenelement, das in widget_list_item.xml definiert ist und aus folgenden Elementen besteht: Zwei TextView-Objekte:

<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>

Um gefälschte Listenelemente bereitzustellen, können Sie das Layout mehrmals einfügen. führt dazu, dass jedes Listenelement identisch ist. Um eindeutige Listenelemente bereitzustellen, folgen Sie diese Schritte:

  1. Erstellen Sie eine Reihe von Attributen für die Textwerte:

    <resources>
        <attr name="widgetTitle" format="string" />
        <attr name="widgetContent" format="string" />
    </resources>
    
  2. Verwenden Sie diese Attribute, um den Text festzulegen:

    <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>
    
  3. Erstellen Sie so viele Stile, wie für die Vorschau erforderlich sind. Definieren Sie die Werte in für jeden Stil:

    <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>
    
  4. Wenden Sie die Stile auf die gefälschten Elemente im Vorschaulayout an:

    <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>