Gerenciar e atualizar o GlanceAppWidget

As seções a seguir descrevem como atualizar GlanceAppWidget e gerenciar o estado dele.

Gerenciar o estado de GlanceAppWidget

A classe GlanceAppWidget fornecida é instanciada sempre que o widget é criado ou requer uma atualização. Portanto, ela precisa ser sem estado e passiva.

O conceito de estado pode ser dividido da seguinte maneira:

  • Estado do aplicativo: o estado ou o conteúdo do app exigido pelo widget. Por exemplo, uma lista de destinos armazenados (ou seja, banco de dados) definida pelo usuário.
  • Estado de resumo: o estado específico que é relevante apenas para o widget do app e não necessariamente modifica ou afeta o estado do app. Por exemplo, uma caixa de seleção foi marcada no widget ou um contador foi aumentado.

Usar estado do aplicativo

Os widgets de apps precisam ser passivos. Cada aplicativo é responsável por gerenciar a camada de dados e processar os estados, como ocioso, carregamento e erro que é refletido na interface do widget.

Por exemplo, o código abaixo recupera os destinos do cache na memória da camada de repositório, fornece a lista armazenada de destinos e exibe uma interface diferente, dependendo do estado:

class DestinationAppWidget : GlanceAppWidget() {

    // ...

    @Composable
    fun MyContent() {
        val repository = remember { DestinationsRepository.getInstance() }
        // Retrieve the cache data everytime the content is refreshed
        val destinations by repository.destinations.collectAsState(State.Loading)

        when (destinations) {
            is State.Loading -> {
                // show loading content
            }

            is State.Error -> {
                // show widget error content
            }

            is State.Completed -> {
                // show the list of destinations
            }
        }
    }
}

Sempre que o estado ou os dados mudam, é responsabilidade do app notificar e atualizar o widget. Consulte Atualizar o GlanceAppWidget para saber mais.

Atualize o GlanceAppWidget.

Conforme explicado na seção Gerenciar o estado do GlanceAppWidget, os widgets de apps são hospedados em um processo diferente. O Glance converte o conteúdo em RemoteViews e o envia para o host. Para atualizar o conteúdo, o Glance precisa recriar a RemoteViews e enviá-la novamente.

Para enviar a atualização, chame o método update da instância GlanceAppWidget, fornecendo context e glanceId:

MyAppWidget().update(context, glanceId)

Para acessar o glanceId, consulte o GlanceAppWidgetManager:

val manager = GlanceAppWidgetManager(context)
val widget = GlanceSizeModeWidget()
val glanceIds = manager.getGlanceIds(widget.javaClass)
glanceIds.forEach { glanceId ->
    widget.update(context, glanceId)
}

Como alternativa, use uma destas extensões GlanceAppWidget update:

// Updates all placed instances of MyAppWidget
MyAppWidget().updateAll(context)

// Iterate over all placed instances of MyAppWidget and update if the state of
// the instance matches the given predicate
MyAppWidget().updateIf<State>(context) { state ->
    state == State.Completed
}

Esses métodos podem ser chamados de qualquer parte do aplicativo. Como são funções suspend, recomendamos iniciá-las fora do escopo da linha de execução principal. No exemplo abaixo, eles são iniciados em um CoroutineWorker:

class DataSyncWorker(
    val context: Context,
    val params: WorkerParameters,
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        // Fetch data or do some work and then update all instance of your widget
        MyAppWidget().updateAll(context)
        return Result.success()
    }
}

Consulte Corrotinas Kotlin no Android (link em inglês) para mais detalhes sobre corrotinas.