Bu sayfada, daha iyi bir kullanıcı deneyimi sağlar.
Widget içeriğini güncellemeyle ilgili optimizasyonlar
Widget içeriğini güncellemek bilgi işlem açısından pahalı olabilir. Pil tüketimini azaltmak için güncelleme türünü, sıklığını ve zamanlamasını optimize edin.
Widget güncellemesi türleri
Bir widget'ı güncellemenin üç yolu vardır: tam güncelleme, kısmi güncelleme ve ise bir veri yenilemesi olduğunu varsayalım. Her biri farklı ve sonuçları.
Aşağıda her güncelleme türü açıklanmakta ve her biri için kod snippet'leri sağlanmaktadır.
Tam güncelleme: Widget'ı tamamen güncellemek için
AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews)
işlevini çağırın. Bu işlem, daha önce sağlananRemoteViews
değerini yeni birRemoteViews
değeriyle değiştirir. Bu, en pahalı hesaplama işlemi gerektiren güncellemedir.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);
Kısmi güncelleme: Widget'ın bölümlerini güncellemek için
AppWidgetManager.partiallyUpdateAppWidget
çağrısı yapın. Bu işlem, yeniRemoteViews
ile daha önce sağlananRemoteViews
'ü birleştirir. Bir widgetupdateAppWidget(int[], RemoteViews)
üzerinden en az bir tam güncelleme almazsa bu yöntem yok sayılır.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);
Koleksiyon verilerini yenileme: Widget'ınızdaki bir koleksiyon görünümünün verilerini geçersiz kılmak için
AppWidgetManager.notifyAppWidgetViewDataChanged
işlevini çağırın. Bu işlem,RemoteViewsFactory.onDataSetChanged
tetikleyicisini etkinleştirir. Bu süre zarfında widget'ta eski veriler gösterilir. Bu yöntemle pahalı görevleri senkronize olarak güvenli bir şekilde gerçekleştirebilirsiniz.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);
Uygulamanızın herhangi bir yerindeyken bu yöntemleri çağırabilirsiniz. Önemli olan
karşılık gelen ile aynı UID
AppWidgetProvider
sınıfı.
Widget'ların ne sıklıkta güncelleneceğini belirleme
Widget'lar, updatePeriodMillis
özelliği için sağlanan değere bağlı olarak düzenli aralıklarla güncellenir. Widget, kullanıcı etkileşimine yanıt olarak güncellenebilir, güncelleme yayınlayabilir veya her ikisini de yapabilir.
Düzenli olarak güncelleme
Periyodik güncellemenin sıklığını kontrol etmek için
appwidget-provider
XML'de AppWidgetProviderInfo.updatePeriodMillis
. Her güncelleme, widget'ı güncellemek için kodu yerleştirebileceğiniz AppWidgetProvider.onUpdate()
yöntemini tetikler. Ancak, projenizin alternatifleri olan
yayın alıcı güncellemelerinin
widget'ınızın verileri eşzamansız olarak yüklemesi gerekiyorsa veya daha fazla zaman alıyorsa
10 saniyeden uzun sürmez. Çünkü 10 saniyeden sonra, sistem
BroadcastReceiver
yanıt vermeyecek.
updatePeriodMillis
, 30 dakikadan kısa değerleri desteklemez. Ancak, düzenli güncellemeleri devre dışı bırakmak isterseniz 0 değerini belirtebilirsiniz.
Kullanıcıların bir yapılandırmadaki güncelleme sıklığını ayarlamalarına izin verebilirsiniz. Örneğin, bir hisse senedi akışının 15 dakikada bir veya yalnızca günde dört kez güncellenmesini isteyebilirler. Bu durumda updatePeriodMillis
değerini 0 olarak ayarlayın ve bunun yerine WorkManager
kullanın.
Kullanıcı etkileşimine yanıt olarak güncelleme
Widget'ı kullanıcı etkileşimine göre güncellemek için önerilen yöntemlerden bazıları şunlardır:
Uygulamanın bir etkinliğinden: Kullanıcının dokunması gibi bir kullanıcı etkileşimine yanıt olarak doğrudan
AppWidgetManager.updateAppWidget
çağrılır.Bildirim veya uygulama widget'ı gibi uzaktan etkileşimlerden: bir
PendingIntent
oluşturun, ardından çağrılanActivity
,Broadcast
veyaService
. Kendi önceliğinizi seçebilirsiniz. Örneğin,PendingIntent
için birBroadcast
seçersenizBroadcastReceiver
'e öncelik vermek üzere bir ön plan yayını seçebilirsiniz.
Yayın etkinliğine yanıt olarak güncelleme
Widget'ın güncellenmesi gereken bir yayın etkinliğine örnek olarak, fotoğraf çektiğini varsayalım. Bu durumda, yeni bir fotoğraf eklendiğinde widget'ı tespit edilir.
JobScheduler
ile bir iş planlayabilir ve JobInfo.Builder.addTriggerContentUri
yöntemini kullanarak tetikleyici olarak bir yayın belirtebilirsiniz.
Yayın için bir BroadcastReceiver
de kaydedebilirsiniz. Örneğin, ACTION_LOCALE_CHANGED
için dinleme.
Ancak bu işlem cihaz kaynaklarını kullandığından bu özelliği dikkatli bir şekilde kullanın ve yalnızca belirli bir yayını dinleyin. Yayınların kullanıma sunulmasıyla birlikte
sınırlamaları
7.0 (API düzeyi 24) ve Android 8.0 (API düzeyi 26) sürümleriyle uygulamalar örtülü kaydedemez
bunların belirli bir kısmı,
istisnalar.
Bir widget'ı BroadcastReceiver'dan güncellerken dikkat edilmesi gerekenler
Widget, aşağıdakiler dahil bir BroadcastReceiver
üzerinden güncellenirse:
AppWidgetProvider
,
güncellemenin süresini ve önceliğini kontrol edin.
Güncelleme süresi
Kural olarak, sistem genellikle uygulamanın içinde çalışan yayın alıcılarına izin verir. ana iş parçacığının, duyarlı olmadığını ve yanıt vermediğini kabul etmeden önce 10 saniyeye kadar çalıştırın bir Uygulama Değil Yanıt Verme (ANR) hatası. Daha uzun sürerse widget'ı güncelledikten sonra aşağıdaki alternatifleri göz önünde bulundurun:
WorkManager
kullanarak görev planlayın.goAsync
yöntemiyle alıcıya daha fazla zaman verin. Bu, alıcılara 30 saniye boyunca yürütme olanağı tanır.
Daha fazla bilgi için Güvenlikle ilgili dikkat edilmesi gereken noktalar ve en iyi uygulamalar başlıklı makaleyi inceleyin.
Güncellemenin önceliği
Varsayılan olarak,
AppWidgetProvider.onUpdate
: Arka plan işlemleri olarak çalışır. Bu, aşırı yüklenmiş sistem kaynaklarının yayın alıcısının çağrılmasında gecikmeye neden olabileceği anlamına gelir. Yayına öncelik vermek için yayını ön plan işlemi yapın.
Örneğin, kullanıcı widget'ın belirli bir bölümüne dokunduğunda PendingIntent.getBroadcast
'e iletilen Intent
'e Intent.FLAG_RECEIVER_FOREGROUND
işaretini ekleyin.
Dinamik öğeler içeren doğru önizlemeler oluşturun
Bu bölümde, aynı reklamda birden fazla öğe görüntülemek için önerilen yaklaşım
koleksiyonu olan bir widget'ın widget önizlemesi
görünüm: yani bir widget kullanan bir widget
ListView
, GridView
veya StackView
.
Widget'ınız bu görünümlerden birini kullanıyorsa doğrudan widget'ın kendisini sunmak düzen, önizlemede hiçbir öğe görüntülenmediğinde yeni bir deneyim yaşayabilirsiniz. Bunun nedeni, koleksiyon görünümü verileri çalışma zamanında dinamik olarak ayarlanır ve bu veriler ilgili resim gösterilmektedir.
Koleksiyon görünümleri içeren widget'ların önizlemelerinin widget seçicide düzgün şekilde gösterilmesi için yalnızca önizleme için ayrılmış ayrı bir düzen dosyası kullanmanızı öneririz. Bu ayrı düzen dosyası, gerçek widget düzenini ve sahte öğeler içeren bir yer tutucu koleksiyon görünümünü içerir. Örneğin, bir
Çok sayıda sahte liste içeren LinearLayout
yer tutucusu sağlayarak ListView
öğeler.
ListView
örneğini açıklamak için ayrı bir düzen dosyasıyla başlayın:
// 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>
AppWidgetProviderInfo
meta verilerinin previewLayout
özelliğini sağlarken önizleme düzeni dosyasını belirtin. initialLayout
özelliği için gerçek widget düzenini belirtmeye ve çalışma zamanında RemoteViews
oluştururken gerçek widget düzenini kullanmaya devam edersiniz.
<appwidget-provider
previewLayout="@layout/widget_previe"
initialLayout="@layout/widget_view" />
Karmaşık liste öğeleri
Liste öğeleri TextView
nesneleri olduğundan önceki bölümdeki örnekte sahte liste öğeleri sağlanmaktadır. Öğeler karmaşık düzenlerse sahte öğeler sağlamak daha karmaşık olabilir.
widget_list_item.xml
içinde tanımlanmış ve şunlardan oluşan bir liste öğesini düşünün
iki TextView
nesnesi var:
<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>
Sahte liste öğeleri sağlamak için düzeni birden fazla kez ekleyebilirsiniz, ancak her liste öğesinin aynı olmasına neden olur. Benzersiz liste öğeleri sağlamak için aşağıdaki adımları uygulayın:
Metin değerleri için bir özellik grubu oluşturun:
<resources> <attr name="widgetTitle" format="string" /> <attr name="widgetContent" format="string" /> </resources>
Metni ayarlamak için aşağıdaki özellikleri kullanın:
<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>
Önizleme için gereken sayıda stil oluşturun. Her stildeki değerleri yeniden tanımlayın:
<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>
Önizleme düzenindeki sahte öğelere stil uygulayın:
<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>