Esta página explica as práticas recomendadas para criar um widget mais avançado e melhorar a experiência do usuário.
Otimizações para atualizar o conteúdo do widget
Atualizar o conteúdo do widget pode ser computacionalmente caro. Para economizar bateria, otimize o tipo, a frequência e o tempo de atualização.
Tipos de atualizações de widgets
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 deles.
Atualização completa:chame
AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews)
para atualizar totalmente o widget. Isso substitui oRemoteViews
fornecido anteriormente por um novoRemoteViews
. Essa é a atualização mais cara em termos de computação.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.partiallyUpdateAppWidget
para atualizar partes do widget. Isso mescla o novoRemoteViews
com oRemoteViews
fornecido anteriormente. Esse método é 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.notifyAppWidgetViewDataChanged
para invalidar os dados de uma visualização de coleção no seu widget. Isso acionaRemoteViewsFactory.onDataSetChanged
. Enquanto isso, os dados antigos são mostrados no widget. Você pode executar 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 atributo
updatePeriodMillis
. O widget pode ser atualizado em resposta à interação do usuário, transmitir
atualizações 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.
Você pode permitir que os usuários ajustem a frequência das atualizações em uma configuração. Por
exemplo, talvez queiram que um mostrador de ações seja atualizado a cada 15 minutos ou apenas quatro
vezes por dia. Nesse caso, defina o 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 diretamente
AppWidgetManager.updateAppWidget
em resposta a uma interação do usuário, como um toque.Em interações remotas, como uma notificação ou um widget de app:construa um
PendingIntent
e atualize o widget usando oActivity
,Broadcast
ouService
invocado. Você pode escolher sua própria prioridade. Por exemplo, se você selecionar umBroadcast
para oPendingIntent
, poderá escolher uma transmissão em primeiro plano para dar prioridade aoBroadcastReceiver
.
Atualização 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 for detectada.
É possível programar um job com JobScheduler
e especificar uma transmissão como o
gatilho usando o método
JobInfo.Builder.addTriggerContentUri
.
Também é possível registrar um BroadcastReceiver
para a transmissão. Por exemplo,
detectar
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 das limitações de
transmissão no Android
7.0 (API de nível 24) e no Android 8.0 (API de nível 26), 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
, fique atento às 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, funcionem por até 10 segundos antes de serem considerados sem resposta e
acionarem um erro de O app não está
respondendo (ANR). Para evitar o bloqueio da
thread principal ao processar a transmissão, use o método
goAsync
. Se a atualização do widget demorar mais, 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 e práticas recomendadas de segurança para mais informações.
Prioridade da atualização
Por padrão, as transmissões, incluindo as 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 receptor de transmissão. Para priorizar a transmissão, faça dela um processo em primeiro plano.
Por exemplo, adicione a flag
Intent.FLAG_RECEIVER_FOREGROUND
ao Intent
transmitido ao PendingIntent.getBroadcast
quando o usuário
toca em uma determinada parte do widget.