Na tej stronie opisujemy zalecane metody tworzenia bardziej zaawansowanych widżetów dla i lepsze wrażenia użytkowników.
Optymalizacje w zakresie aktualizowania zawartości widżetów
Aktualizowanie zawartości widżetu może być kosztowne pod względem obliczeń. Aby oszczędzać baterię zoptymalizować typ, częstotliwość i czas aktualizacji.
Rodzaje aktualizacji widżetów
Widżet można zaktualizować na 3 sposoby: pełną aktualizację, aktualizację częściową lub w przypadku widżetu kolekcji – odświeżenie danych. Każdy z nich ma inny koszty obliczeniowe i ich konsekwencje.
Poniżej opisujemy poszczególne typy aktualizacji i przedstawiamy fragmenty kodu dla każdego z nich.
Pełna aktualizacja: zadzwoń pod numer
AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews)
aby w pełni zaktualizować widżet. Spowoduje to zastąpienie poprzednio podanej wartościRemoteViews
z nowymRemoteViews
To najdroższa aktualizacja pod względem obliczeń.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);
Częściowa aktualizacja: połączenie
AppWidgetManager.partiallyUpdateAppWidget
. aby zaktualizować części widżetu. Spowoduje to scalenie nowejRemoteViews
z podany wcześniejRemoteViews
. Ta metoda jest ignorowana, jeśli widżet nie otrzyma co najmniej jednej pełnej aktualizacji doupdateAppWidget(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);
Odświeżanie danych kolekcji: połączenie
AppWidgetManager.notifyAppWidgetViewDataChanged
. , aby unieważnić dane widoku kolekcji w widżecie. To wyzwalaRemoteViewsFactory.onDataSetChanged
Do tego czasu w widżecie wyświetlane są stare dane. Możesz bezpiecznie synchronicznie z wykorzystaniem tej metody do wykonywania kosztownych zadań.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);
Możesz wywoływać te metody z dowolnego miejsca w aplikacji, jeśli tylko aplikacja ma
taki sam identyfikator UID jak odpowiedni identyfikator
AppWidgetProvider
.
Określanie częstotliwości aktualizowania widżetu
Widżety są aktualizowane okresowo w zależności od wartości atrybutu
updatePeriodMillis
. Widżet może się aktualizować w odpowiedzi na interakcje użytkownika, komunikaty
lub jedno i drugie.
Aktualizuj okresowo
Można kontrolować częstotliwość aktualizacji okresowych, określając wartość dla
AppWidgetProviderInfo.updatePeriodMillis
w pliku XML appwidget-provider
. Każdy
aktualizacja powoduje uruchomienie metody AppWidgetProvider.onUpdate()
, w której
aby zaktualizować widżet. Rozważ jednak alternatywy dla
aktualizacje odbiornika opisane w
tej sekcji, jeśli widżet musi ładować dane asynchronicznie lub pobierać więcej
trwa dłużej niż 10 sekund, ponieważ po 10 sekundach system uznaje
BroadcastReceiver
, aby nie odpowiadał.
updatePeriodMillis
nie obsługuje wartości krótszych niż 30 minut. Jeśli jednak
Jeśli chcesz wyłączyć okresowe aktualizacje, możesz wpisać 0.
Możesz zezwolić użytkownikom na dostosowywanie częstotliwości aktualizacji w konfiguracji. Dla:
Na przykład mogą chcieć, aby pasek giełdowy aktualizował się co 15 minut lub tylko co 4 minuty.
razy dziennie. W tym przypadku ustaw updatePeriodMillis
na 0 i użyj wartości
WorkManager
.
Aktualizacja w odpowiedzi na interakcję użytkownika
Oto kilka zalecanych sposobów aktualizowania widżetu w zależności od interakcji użytkownika:
Z poziomu aktywności w aplikacji: zadzwoń bezpośrednio
AppWidgetManager.updateAppWidget
w odpowiedzi na interakcję użytkownika, taką jak kliknij go.Z poziomu interakcji zdalnych, takich jak powiadomienia lub widżet aplikacji: utwórz
PendingIntent
, a następnie zaktualizuj widżet zActivity
,Broadcast
lubService
. Możesz wybrać własny priorytet. Dla: np. jeśli wybierzeszBroadcast
dla elementuPendingIntent
, możesz wybrać komunikat na pierwszym planie, który przekaże Priorytet:BroadcastReceiver
.
Aktualizacja w odpowiedzi na transmitowane wydarzenie
Przykładem transmitowanego wydarzenia, które wymaga aktualizacji widżetu, jest sytuacja, w której robi zdjęcie. Pozwala to aktualizować widżet, gdy nowe zdjęcie .
Możesz zaplanować zadanie za pomocą funkcji JobScheduler
i określić transmisję jako
za pomocą funkcji
JobInfo.Builder.addTriggerContentUri
.
.
Możesz też zarejestrować BroadcastReceiver
dla transmisji, na przykład
nasłuchuję
ACTION_LOCALE_CHANGED
Jednak zużywanie zasobów urządzenia jest wykorzystywane, dlatego zachowaj ostrożność i słuchaj
tylko do konkretnej transmisji. Dzięki wprowadzeniu transmisji na żywo
ograniczenia na Androidzie
7.0 (poziom interfejsu API 24) i Android 8.0 (poziom interfejsu API 26) nie można domyślnie rejestrować aplikacji
komunikatów w plikach manifestu, z uwzględnieniem pewnych
wyjątkami.
Uwagi na temat aktualizowania widżetu z BroadcastReceiver
Jeśli widżet jest aktualizowany z elementu BroadcastReceiver
, w tym
AppWidgetProvider
, pamiętaj o następujących kwestiach związanych z
czasu trwania i priorytetu aktualizacji widżetu.
Czas trwania aktualizacji
System zazwyczaj dopuszcza odbiorniki, które zwykle działają na poziomie w wątku głównym, należy uruchomić go przez maksymalnie 10 sekund, zanim uznamy, że nie odpowiada uruchomienie polecenia Application Not Reagowanie na błąd (ANR). Jeśli potrwa to dłużej, zaktualizuj widżet, rozważ inne alternatywne rozwiązania:
Zaplanuj zadanie za pomocą funkcji
WorkManager
.Daj odbiorcy więcej czasu,
goAsync
. Dzięki temu odbiorcy będą wykonywać 30 sekund.
Zobacz Uwagi na temat bezpieczeństwa i najważniejsze informacje sprawdzone metody, i informacjami o nich.
Priorytet aktualizacji
Domyślnie komunikaty, w tym te przeprowadzone za pomocą
AppWidgetProvider.onUpdate
– jest uruchamiany jako procesy w tle. Oznacza to, że
przeciążone zasoby systemowe mogą powodować opóźnienie wywołania transmisji
odbiorcy. Aby nadać transmisji priorytetową, ustaw ją jako proces na pierwszym planie.
Na przykład dodaj parametr
Intent.FLAG_RECEIVER_FOREGROUND
flaga do Intent
przekazywanej do PendingIntent.getBroadcast
, gdy użytkownik
i kliknie określoną część widżetu.
Tworzenie dokładnych podglądów z uwzględnieniem elementów dynamicznych
W tej sekcji opisujemy zalecane metody wyświetlania wielu elementów w
podgląd widżetu z kolekcją
– czyli widżet, który korzysta z tagu
ListView
, GridView
lub StackView
.
Jeśli widżet korzysta z jednego z tych widoków, utworzenie skalowalnego podglądu bezpośrednio udostępniam rzeczywisty widżet układ pogarsza gdy na podglądzie widżetu nie ma żadnych elementów. Dzieje się tak, ponieważ dane widoku kolekcji są ustawiane dynamicznie w czasie działania i wyglądają podobnie do na ilustracji 1.
Aby podglądy widżetów z widokami kolekcji były prawidłowo wyświetlane w widżecie
zalecamy zachowanie osobnego pliku układu przeznaczonego tylko na
podgląd. Ten oddzielny plik układu zawiera rzeczywisty układ widżetu oraz element
zastępczy widok kolekcji z fałszywymi elementami. Możesz na przykład udawać
ListView
, podając obiekt zastępczy LinearLayout
z kilkoma fałszywymi listami
elementy(ów).
Aby pokazać przykład dla elementu ListView
, zacznij od osobnego pliku układu:
// 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>
Określ plik układu podglądu, podając atrybut previewLayout
metadane AppWidgetProviderInfo
. Nadal określasz rzeczywisty układ widżetu
dla atrybutu initialLayout
i używać rzeczywistego układu widżetu, gdy
podczas tworzenia obiektu RemoteViews
w czasie działania.
<appwidget-provider
previewLayout="@layout/widget_previe"
initialLayout="@layout/widget_view" />
Złożone elementy listy
Przykład w poprzedniej sekcji zawiera fałszywe elementy listy, ponieważ
elementy to TextView
. Jest taka możliwość
dostarczanie fałszywych przedmiotów jest bardziej złożone, jeśli elementy mają złożone układy.
Zastanów się nad elementem listy zdefiniowanym w zasadzie widget_list_item.xml
i składanym z tych elementów:
dwa obiekty 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>
Aby podać fałszywe pozycje listy, możesz dodać układ kilka razy, ale w tym przypadku sprawi, że elementy listy będą identyczne. Aby podać unikalne elementy listy, postępuj zgodnie z wykonaj te czynności:
Utwórz zestaw atrybutów dla wartości tekstowych:
<resources> <attr name="widgetTitle" format="string" /> <attr name="widgetContent" format="string" /> </resources>
Użyj tych atrybutów, aby ustawić tekst:
<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>
Utwórz dowolną liczbę stylów do podglądu. Zdefiniuj ponownie wartości w w każdym stylu:
<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>
Zastosuj style do fałszywych elementów w układzie podglądu:
<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>