Gelişmiş widget oluşturma

Bu sayfada, kullanıcı deneyimini iyileştirmeye yardımcı olur.

Widget içeriğini güncellemek için optimizasyonlar

Widget içeriğini güncellemek işlem yükü açısından pahalı olabilir. Pilden tasarruf etmek için tüketimi, güncelleme türünü, sıklığını ve zamanlamayı optimize edin.

Widget güncellemesi türleri

Bir widget'ı güncellemenin üç yolu vardır: tam güncelleme, kısmi güncelleme ve koleksiyonu widget'ında veri yenileme işlemi yapılır. Her biri farklı ve sonuçları.

Aşağıda, her güncelleme türü açıklanmakta ve her biri için kod snippet'leri sunulmaktadır.

  • Güncellemenin tamamı: AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews) numaralı telefonu arayın widget'ı tamamen güncelleyin. Bu, daha önce sağlanan RemoteViews - yeni bir RemoteViews. Bu, işlem açısından en pahalı 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: arama AppWidgetManager.partiallyUpdateAppWidget widget'ın belirli bölümlerini güncelleyin. Bu işlem, yeni RemoteViews öğesini önceden sağlanan RemoteViews. Bir widget updateAppWidget(int[], RemoteViews) üzerinden en az bir tam güncelleme almaz.

    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: çağrı AppWidgetManager.notifyAppWidgetViewDataChanged kullanarak widget'ınızdaki bir koleksiyon görünümünün verilerini geçersiz kılabilirsiniz. Bu, tetikleyici RemoteViewsFactory.onDataSetChanged. Bu sırada widget'ta eski veriler gösterilir. Güvenle pahalı görevleri bu yöntemle eşzamanlı olarak 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ı.

Bir widget'ın ne sıklıkta güncelleneceğini belirleme

Widget'lar, updatePeriodMillis özelliğini gönderin. Widget, kullanıcı etkileşimine bağlı olarak güncellenebilir. veya her ikisini birden yapabilirsiniz.

Düzenli aralıklarla güncelleme

Periyodik güncellemenin sıklığını kontrol etmek için appwidget-provider XML'de AppWidgetProviderInfo.updatePeriodMillis. Her biri güncelleme, AppWidgetProvider.onUpdate() yöntemini tetikler. Bu yöntemde widget'ı güncellemek için kod yerleştirebilir. 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 fazladır. Çünkü 10 saniyeden sonra, sistem bir BroadcastReceiver yanıt vermeyecek.

updatePeriodMillis, 30 dakikadan kısa değerleri desteklemiyor. Ancak, periyodik güncellemeleri devre dışı bırakmak istiyorsanız 0 değerini belirtebilirsiniz.

Kullanıcıların bir yapılandırmada güncellemelerin sıklığını ayarlamasına izin verebilirsiniz. Örneğin, bir borsa takip cihazının her 15 dakikada bir veya yalnızca dört dakikada bir güncellenmesini günde birkaç kez. Bu durumda, updatePeriodMillis değerini 0 olarak ayarlayın ve Bunun yerine WorkManager.

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: Doğrudan arama AppWidgetManager.updateAppWidget, şu gibi bir kullanıcı etkileşimine yanıt olarak: kullanıcının dokunuşu olarak değişir.

  • Bildirim veya uygulama widget'ı gibi uzaktan etkileşimlerden: bir PendingIntent oluşturun, ardından çağrılan Activity, Broadcast veya Service. Kendi önceliğinizi seçebilirsiniz. Örneğin, Örneğin, PendingIntent için bir Broadcast seçerseniz bir ön plan yayını yapabilirsiniz. BroadcastReceiver öncelik.

Yayın etkinliğine yanıt olarak güncelleme

Widget'ın güncellenmesi gereken bir yayın etkinliğine örnek olarak, bir fotoğraf çektiğini varsayalım. Bu durumda, yeni bir fotoğraf eklendiğinde widget'ı tespit edilir.

JobScheduler ile bir iş planlayabilir ve tetikleyicinin JobInfo.Builder.addTriggerContentUri yöntemidir.

Ayrıca yayın için bir BroadcastReceiver kaydettirebilirsiniz. Örneğin, dinleniyor ACTION_LOCALE_CHANGED Ancak bu işlem cihaz kaynaklarını tükettiği için bunu yaparken dikkatli olun ve dinleyin belirli bir yayın ile ilişkilendirilir. 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.

BroadcastRecipientr'dan widget güncellerken dikkat edilmesi gereken noktalar

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

  • Alıcıya goAsync yöntemini kullanabilirsiniz. Bu, alıcıların 30 saniye boyunca yürütmesini sağlar.

Güvenlikle ilgili olarak göz önünde bulundurulması gerekenler ve en iyi daha fazla bilgi için ekleyebilirsiniz.

Güncellemenin önceliği

Varsayılan olarak, AppWidgetProvider.onUpdate: Arka plan işlemleri olarak çalışır. Bunun anlamı şudur: sistem kaynaklarının aşırı yüklenmesi, yayının çağrılmasında gecikmeye neden olabilir alıcı. Yayına öncelik vermek için yayını ön plan işlemi yapın.

Örneğin, Intent.FLAG_RECEIVER_FOREGROUND kullanıcı tarafından gerçekleştirildiğinde PendingIntent.getBroadcast öğesine iletilen Intent öğesine işaret widget'ın belirli bir bölümüne dokunduğunda,

Dinamik öğeler içeren doğru önizlemeler oluşturun

Şekil 1: Liste öğesi görüntülenmeyen bir widget önizlemesi

Bu bölümde, aynı görünümde 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.

Widget'ların koleksiyon görünümlerine sahip önizlemelerinin widget'ta düzgün bir şekilde görüntülenmesini sağlamak için yalnızca önizle. Bu ayrı düzen dosyası, gerçek widget düzenini ve bir sahte öğeler içeren yer tutucu koleksiyon görünümü Örneğin, bir Çok sayıda sahte liste içeren LinearLayout yer tutucusu sağlayarak ListView öğeler.

ListView örneğini göstermek 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>

Şu öğenin previewLayout özelliğini sağlarken önizleme düzeni dosyasını belirtin: AppWidgetProviderInfo meta verileri. Yine de gerçek widget düzenini belirtirsiniz ve aşağıdaki durumlarda gerçek widget düzenini kullanın:initialLayout çalışma zamanında bir RemoteViews oluşturuyoruz.

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

Karmaşık liste öğeleri

Önceki bölümdeki örnek sahte liste öğeleri sağlıyor çünkü öğe TextView nesne. Bu, öğeler karmaşık düzenlerse sahte öğelerin sağlanması daha karmaşıktır.

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 şu adımları uygulayın:

  1. Metin değerleri için bir özellik grubu oluşturun:

    <resources>
        <attr name="widgetTitle" format="string" />
        <attr name="widgetContent" format="string" />
    </resources>
    
  2. Metni ayarlamak için şu ö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>
    
  3. Önizleme için gereken sayıda stil oluşturun. Şuradaki değerleri yeniden tanımla: her 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. Ö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>