Halaman ini menjelaskan praktik yang direkomendasikan untuk membuat widget yang lebih canggih guna memberikan pengalaman pengguna yang lebih baik.
Pengoptimalan untuk memperbarui konten widget
Memperbarui konten widget dapat memerlukan biaya komputasi yang tinggi. Untuk menghemat konsumsi baterai, optimalkan jenis, frekuensi, dan waktu update.
Jenis update widget
Ada tiga cara untuk mengupdate widget: update penuh, update parsial, dan, dalam kasus widget koleksi, pemuatan ulang data. Masing-masing memiliki biaya dan konsekuensi komputasi yang berbeda.
Berikut ini penjelasan setiap jenis update dan cuplikan kode untuk masing-masing jenis.
- Update penuh: panggil
AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews)untuk mengupdate widget sepenuhnya. Tindakan ini akan menggantikanRemoteViewsyang disediakan sebelumnya denganRemoteViewsbaru. Ini adalah update yang paling mahal secara komputasi.
val appWidgetManager = AppWidgetManager.getInstance(context) val remoteViews = RemoteViews(context.packageName, R.layout.widgetlayout).apply { setTextViewText(R.id.textview_widget_layout1, "Updated text1") setTextViewText(R.id.textview_widget_layout2, "Updated text2") } appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
- Update parsial: panggil
AppWidgetManager.partiallyUpdateAppWidgetuntuk mengupdate bagian widget. Tindakan ini akan menggabungkanRemoteViewsbaru denganRemoteViewsyang disediakan sebelumnya. Metode ini diabaikan jika widget tidak menerima setidaknya satu update lengkap melaluiupdateAppWidget(int[], RemoteViews).
val appWidgetManager = AppWidgetManager.getInstance(context) val remoteViews = RemoteViews(context.packageName, R.layout.widgetlayout).apply { setTextViewText(R.id.textview_widget_layout, "Updated text") } appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteViews)
- Memperbarui data koleksi: panggil
AppWidgetManager.notifyAppWidgetViewDataChangeduntuk membatalkan validasi data tampilan koleksi di widget Anda. Tindakan ini akan memicuRemoteViewsFactory.onDataSetChanged. Sementara itu, data lama akan ditampilkan di widget. Anda dapat melakukan tugas yang berat secara sinkron dengan aman menggunakan metode ini.
val appWidgetManager = AppWidgetManager.getInstance(context) appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview)
Anda dapat memanggil metode ini dari mana saja di aplikasi, asalkan aplikasi memiliki
UID yang sama dengan class
AppWidgetProvider yang sesuai.
Menentukan frekuensi update widget
Widget diperbarui secara berkala bergantung pada nilai yang diberikan untuk atribut
updatePeriodMillis. Widget dapat diupdate sebagai respons terhadap interaksi pengguna, update
siaran, atau keduanya.
Update secara berkala
Anda dapat mengontrol frekuensi update berkala dengan menentukan nilai untuk
AppWidgetProviderInfo.updatePeriodMillis di XML appwidget-provider. Setiap
update akan memicu metode AppWidgetProvider.onUpdate(), yang merupakan tempat Anda
dapat menempatkan kode untuk mengupdate widget. Namun, pertimbangkan alternatif untuk
update penerima siaran yang dijelaskan di
bagian berikut jika widget Anda perlu memuat data secara asinkron atau memerlukan waktu lebih
dari 10 detik untuk mengupdate, karena setelah 10 detik, sistem akan menganggap
BroadcastReceiver tidak responsif.
updatePeriodMillis tidak mendukung nilai kurang dari 30 menit. Namun, jika
ingin menonaktifkan update berkala, Anda dapat menentukan 0.
Anda dapat mengizinkan pengguna menyesuaikan frekuensi update dalam konfigurasi. Misalnya, mereka mungkin ingin ticker saham diperbarui setiap 15 menit atau hanya empat
kali sehari. Dalam hal ini, tetapkan updatePeriodMillis ke 0 dan gunakan
WorkManager.
Memperbarui sebagai respons terhadap interaksi pengguna
Berikut beberapa cara yang direkomendasikan untuk memperbarui widget berdasarkan interaksi pengguna:
Dari aktivitas aplikasi: panggil langsung
AppWidgetManager.updateAppWidgetsebagai respons terhadap interaksi pengguna, seperti ketukan pengguna.Dari interaksi jarak jauh, seperti notifikasi atau widget aplikasi: buat
PendingIntent, lalu update widget dariActivity,Broadcast, atauServiceyang dipanggil. Anda dapat memilih prioritas Anda sendiri. Misalnya, jika memilihBroadcastuntukPendingIntent, Anda dapat memilih siaran latar depan untuk memberikan prioritasBroadcastReceiver.
Memperbarui sebagai respons terhadap peristiwa siaran
Contoh peristiwa siaran yang memerlukan widget untuk diupdate adalah saat pengguna mengambil foto. Dalam hal ini, Anda ingin mengupdate widget saat foto baru terdeteksi.
Anda dapat menjadwalkan pekerjaan dengan WorkManager dan menentukan pemicu URI konten menggunakan metode Constraints.Builder.addContentUriTrigger.
Anda juga dapat mendaftarkan BroadcastReceiver untuk siaran—misalnya,
memproses ACTION_LOCALE_CHANGED.
Namun, karena hal ini menggunakan resource perangkat, gunakan dengan hati-hati dan hanya dengarkan siaran tertentu. Dengan diperkenalkannya batasan siaran di Android 7.0 (level API 24) dan Android 8.0 (level API 26), aplikasi tidak dapat mendaftarkan siaran implisit dalam manifesnya, dengan pengecualian tertentu.
Pertimbangan saat mengupdate widget dari BroadcastReceiver
Jika widget diupdate dari BroadcastReceiver, termasuk
AppWidgetProvider, perhatikan pertimbangan berikut terkait
durasi dan prioritas update widget.
Durasi update
Sebagai aturan, sistem memungkinkan penerima siaran, yang biasanya berjalan di thread utama aplikasi, berjalan hingga 10 detik sebelum menganggapnya tidak responsif dan memicu error Aplikasi Tidak Merespons (ANR). Untuk menghindari pemblokiran
thread utama saat menangani siaran, gunakan
metode goAsync. Jika perlu waktu lebih lama untuk mengupdate widget, pertimbangkan
untuk menjadwalkan tugas menggunakan WorkManager.
Caution: Any work you do here blocks further broadcasts until it completes,
so it can slow the receiving of later events.
Lihat Pertimbangan keamanan dan praktik terbaik untuk mengetahui informasi selengkapnya.
Prioritas update
Secara default, siaran—termasuk yang dibuat menggunakan
AppWidgetProvider.onUpdate—berjalan sebagai proses latar belakang. Artinya,
resource sistem yang kelebihan beban dapat menyebabkan penundaan dalam pemanggilan penerima
siaran. Untuk memprioritaskan siaran, jadikan siaran sebagai proses latar depan.
Misalnya, tambahkan flag Intent.FLAG_RECEIVER_FOREGROUND
ke Intent yang diteruskan ke PendingIntent.getBroadcast saat pengguna
mengetuk bagian tertentu dari widget.