На этой странице изложены рекомендуемые методы создания более продвинутого виджета для улучшения пользовательского опыта.
Оптимизация обновления содержимого виджета.
Обновление содержимого виджета может быть ресурсоемким процессом. Для экономии заряда батареи оптимизируйте тип, частоту и время обновления.
Типы обновлений виджетов
Существует три способа обновления виджета: полное обновление, частичное обновление и, в случае виджета-коллекции, обновление данных. Каждый из них имеет разные вычислительные затраты и последствия.
Ниже приведено описание каждого типа обновления и фрагменты кода для каждого из них.
Полное обновление: вызовите
AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews), чтобы полностью обновить виджет. Это заменит ранее предоставленныеRemoteViewsна новыеRemoteViews. Это наиболее ресурсоемкое обновление.Котлин
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);
Частичное обновление: вызовите
AppWidgetManager.partiallyUpdateAppWidgetдля обновления частей виджета. Это объединит новыеRemoteViewsс ранее предоставленнымиRemoteViews. Этот метод игнорируется, если виджет не получил хотя бы одно полное обновление черезupdateAppWidget(int[], RemoteViews).Котлин
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);
Обновление данных коллекции: вызовите
AppWidgetManager.notifyAppWidgetViewDataChanged, чтобы аннулировать данные представления коллекции в вашем виджете. Это вызоветRemoteViewsFactory.onDataSetChanged. В промежутке в виджете будут отображаться старые данные. С помощью этого метода вы можете безопасно выполнять ресурсоемкие задачи синхронно.Котлин
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);
Эти методы можно вызывать из любого места в вашем приложении, при условии, что приложение имеет тот же UID, что и соответствующий класс AppWidgetProvider .
Определите, как часто следует обновлять виджет.
Виджеты обновляются периодически в зависимости от значения атрибута updatePeriodMillis . Обновление виджета может происходить в ответ на действия пользователя, трансляцию обновлений или и то, и другое.
Периодически обновлять
Вы можете управлять частотой периодического обновления, указав значение для AppWidgetProviderInfo.updatePeriodMillis в XML-файле appwidget-provider . Каждое обновление запускает метод AppWidgetProvider.onUpdate() , в котором вы можете разместить код для обновления виджета. Однако, если вашему виджету необходимо асинхронно загружать данные или обновление занимает более 10 секунд, рассмотрите альтернативные варианты обновления BroadcastReceiver, описанные в следующем разделе, поскольку по истечении 10 секунд система считает BroadcastReceiver не отвечающим на запросы.
updatePeriodMillis не поддерживает значения меньше 30 минут. Однако, если вы хотите отключить периодические обновления, вы можете указать 0.
В настройках можно указать частоту обновлений для пользователей. Например, они могут захотеть, чтобы биржевой тикер обновлялся каждые 15 минут или только четыре раза в день. В этом случае установите параметр updatePeriodMillis равным 0 и используйте WorkManager .
Обновление в ответ на взаимодействие с пользователем.
Вот несколько рекомендуемых способов обновления виджета в зависимости от взаимодействия с пользователем:
В активности приложения: напрямую вызовите метод
AppWidgetManager.updateAppWidgetв ответ на взаимодействие пользователя, например, на касание экрана.При удаленном взаимодействии, например, с уведомлением или виджетом приложения: создайте объект
PendingIntent, а затем обновите виджет из вызваннойActivity,BroadcastилиService. Вы можете выбрать собственный приоритет. Например, если вы выберетеBroadcastдляPendingIntent, вы можете выбрать широковещательную рассылку в фоновом режиме , чтобы присвоить приоритетBroadcastReceiver.
Обновление в связи с трансляцией события.
Примером широковещательного события, требующего обновления виджета, является момент, когда пользователь делает фотографию. В этом случае необходимо обновлять виджет при обнаружении новой фотографии.
Вы можете запланировать задание с помощью JobScheduler и указать широковещательную рассылку в качестве триггера, используя метод JobInfo.Builder.addTriggerContentUri .
Вы также можете зарегистрировать BroadcastReceiver для широковещательной рассылки — например, для прослушивания события ACTION_LOCALE_CHANGED . Однако, поскольку это потребляет ресурсы устройства, используйте это с осторожностью и прослушивайте только конкретную широковещательную рассылку. С введением ограничений на широковещательную рассылку в Android 7.0 (уровень API 24) и Android 8.0 (уровень API 26) приложения не могут регистрировать неявные широковещательные рассылки в своих манифестах, за некоторыми исключениями .
Рекомендации при обновлении виджета из BroadcastReceiver
Если виджет обновляется из BroadcastReceiver , включая AppWidgetProvider , следует учитывать следующие моменты, касающиеся продолжительности и приоритета обновления виджета.
Продолжительность обновления
Как правило, система позволяет широковещательным приемникам, которые обычно работают в основном потоке приложения, работать до 10 секунд, прежде чем считать их не отвечающими и вызвать ошибку « Приложение не отвечает » (ANR). Чтобы избежать блокировки основного потока во время обработки широковещательного сообщения, используйте метод goAsync . Если обновление виджета занимает больше времени, рассмотрите возможность планирования задачи с помощью WorkManager .
Caution: Any work you do here blocks further broadcasts until it completes,
so it can slow the receiving of later events.
Дополнительную информацию см. в разделе «Вопросы безопасности и лучшие практики» .
Приоритет обновления
По умолчанию широковещательные сообщения, в том числе и те, которые отправляются с помощью AppWidgetProvider.onUpdate , выполняются в фоновом режиме. Это означает, что перегрузка системных ресурсов может вызвать задержку в вызове приемника широковещательных сообщений. Чтобы придать широковещательному сообщению приоритет, переведите его в режим переднего плана.
Например, добавьте флаг Intent.FLAG_RECEIVER_FOREGROUND к Intent , передаваемому в PendingIntent.getBroadcast когда пользователь нажимает на определенную часть виджета.
