Esta página explica as práticas recomendadas para criar um widget mais avançado para uma melhor experiência do usuário.
Otimizações para atualizar o conteúdo do widget
A atualização do conteúdo do widget pode ser computacionalmente cara. Para economizar o consumo de bateria, otimize o tipo, a frequência e o tempo de atualização.
Tipos de atualizações de widget
Há três maneiras de atualizar um widget: uma atualização completa, uma atualização parcial e, no caso de um widget de coleção, uma atualização de dados. Cada um tem custos computacionais e ramificações diferentes.
A seguir, descrevemos cada tipo de atualização e fornecemos snippets de código para cada um.
Atualização completa: chame
AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews)para atualizar totalmente o widget. Isso substitui oRemoteViewsfornecido anteriormente por um novoRemoteViews. Essa é a atualização mais cara do ponto de vista computacional.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);
Atualização parcial:chame
AppWidgetManager.partiallyUpdateAppWidgetpara atualizar partes do widget. Isso mescla o novoRemoteViewscom oRemoteViewsfornecido anteriormente. Esse método será ignorado se um widget não receber pelo menos uma atualização completa usandoupdateAppWidget(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);
Atualização de dados da coleção: chame
AppWidgetManager.notifyAppWidgetViewDataChangedpara invalidar os dados de uma visualização de coleção no widget. Isso acionaRemoteViewsFactory.onDataSetChanged. Enquanto isso, os dados antigos são exibidos no widget. É possível realizar tarefas caras de forma síncrona com segurança usando esse método.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);
É possível chamar esses métodos de qualquer lugar no app, desde que ele tenha o
mesmo UID da classe
AppWidgetProvider correspondente.
Determinar a frequência de atualização de um widget
Os widgets são atualizados periodicamente, dependendo do valor fornecido para o
updatePeriodMillis
atributo. O widget pode ser atualizado em resposta à interação do usuário, atualizações de transmissão ou ambos.
Atualizar periodicamente
É possível controlar a frequência da atualização periódica especificando um valor para AppWidgetProviderInfo.updatePeriodMillis no XML appwidget-provider. Cada atualização aciona o método AppWidgetProvider.onUpdate(), que é onde você pode colocar o código para atualizar o widget. No entanto, considere as alternativas para
atualizações de broadcast receiver descritas em uma
seção a seguir se o widget precisar carregar dados de forma assíncrona ou levar mais
de 10 segundos para atualizar. Isso porque, após 10 segundos, o sistema considera um
BroadcastReceiver como não responsivo.
updatePeriodMillis não aceita valores menores que 30 minutos. No entanto, se você quiser desativar as atualizações periódicas, especifique 0.
É possível permitir que os usuários ajustem a frequência de atualizações em uma configuração. Por exemplo, eles podem querer que um mostrador de ações seja atualizado a cada 15 minutos ou apenas quatro vezes por dia. Nesse caso, defina updatePeriodMillis como 0 e use
WorkManager.
Atualizar em resposta a uma interação do usuário
Confira algumas maneiras recomendadas de atualizar o widget com base na interação do usuário:
De uma atividade do app:chame
AppWidgetManager.updateAppWidgetdiretamente em resposta a uma interação do usuário, como um toque.De interações remotas, como uma notificação ou um widget de app:construa um
PendingIntente atualize o widget daActivity,BroadcastouServiceinvocada. Você pode escolher sua própria prioridade. Por exemplo, se você selecionar umBroadcastpara oPendingIntent, poderá escolher uma transmissão em primeiro plano para darBroadcastReceiverprioridade.
Atualizar em resposta a um evento de transmissão
Um exemplo de evento de transmissão que exige a atualização de um widget é quando o usuário tira uma foto. Nesse caso, você quer atualizar o widget quando uma nova foto é detectada.
É possível agendar um job com JobScheduler e especificar uma transmissão como o
acionador usando o
JobInfo.Builder.addTriggerContentUri
método.
Também é possível registrar um BroadcastReceiver para a transmissão. Por exemplo,
ouvir
ACTION_LOCALE_CHANGED.
No entanto, como isso consome recursos do dispositivo, use com cuidado e ouça apenas a transmissão específica. Com a introdução de limitações de transmissão no Android 7.0 (nível 24 da API) e no Android 8.0 (nível 26 da API), os apps não podem registrar transmissões implícitas nos manifestos, com algumas exceções.
Considerações ao atualizar um widget de um BroadcastReceiver
Se o widget for atualizado de um BroadcastReceiver, incluindo AppWidgetProvider, esteja ciente das seguintes considerações sobre a duração e a prioridade de uma atualização de widget.
Duração da atualização
Como regra geral, o sistema permite que os broadcast receivers, que geralmente são executados na linha de execução principal do app, sejam executados por até 10 segundos antes de serem considerados não responsivos e
acionarem um erro de O app não está
respondendo (ANR). Para evitar o bloqueio da
linha de execução principal ao processar a transmissão, use o
goAsync método. Se levar
mais tempo para atualizar o widget, considere agendar uma tarefa
usando WorkManager.
Caution: Any work you do here blocks further broadcasts until it completes,
so it can slow the receiving of later events.
Consulte Considerações de segurança e práticas recomendadas para mais informações.
Prioridade da atualização
Por padrão, as transmissões, incluindo aquelas feitas usando AppWidgetProvider.onUpdate, são executadas como processos em segundo plano. Isso significa que recursos de sistema sobrecarregados podem causar um atraso na invocação do broadcast receiver. Para priorizar a transmissão, faça dela um processo em primeiro plano.
Por exemplo, adicione a
Intent.FLAG_RECEIVER_FOREGROUND
flag ao Intent transmitido para o PendingIntent.getBroadcast quando o usuário
tocar em uma determinada parte do widget.