Conceitos e arquitetura do Remote Compose

O Remote Compose é uma biblioteca do Jetpack que permite criar uma interface com APIs no estilo do Compose no app e mostrá-la em processos do sistema, como widgets de apps ou do Wear OS. O app registra a IU como um documento compacto, e um player no processo do host a renderiza e processa interações, mudanças de estado e animações localmente, sem chamar o app.

Este guia explica a arquitetura do Remote Compose e como ela é diferente do Jetpack Compose padrão. Este guia se concentra na criação de interfaces com componentes.

Casos de uso do Remote Compose

O Remote Compose pode ser usado em qualquer plataforma com um player compatível. No Android, ele é usado em widgets de apps e do Wear OS.

Como funciona: arquitetura de três blocos

A diferença arquitetônica fundamental entre o Remote Compose e o Jetpack Compose padrão está na separação entre a definição da interface e a execução em três blocos de alto nível:

  • Criar o documento: o app executa as funções @RemoteComposable para registrar um documento, que é uma descrição compacta e serializada da interface, incluindo o layout, o estado remoto e as ações. Quando os dados mudam, o app pode registrar e enviar um novo documento.
  • Transportar o documento para o host remoto: o app transmite o documento para o host, o processo que o exibe, como um acesso rápido ou o Wear OS.
  • Reproduzir o documento: um player do Remote Compose no host renderiza o documento e processa o layout, a entrada, as mudanças de estado da UX e as animações localmente, sem chamar o app.

Essa arquitetura oferece benefícios principais que reduzem diretamente a latência:

  • Tamanho pequeno do documento: os snapshots de documentos serializados permanecem compactos e leves.
  • Menos idas e voltas: como o player do host remoto processa as interações e as mudanças de estado localmente, as comunicações de ida e volta para o aplicativo ou servidor são minimizadas.

Analogia com página da Web / HTML: o Compose remoto funciona de maneira semelhante à veiculação de uma página da Web. O servidor de apps gera e envia uma estrutura de HTML/documento uma vez, e o host do navegador a renderiza e processa as interações localmente sem consultar o back-end constantemente.

Comunicação entre o processo do app e o processo do host remoto para o Compose remoto
Figura 1. Os três blocos da arquitetura do Compose Remoto

Componentes

O Remote Compose oferece componentes de interface de alto nível para estruturar layouts. Use os componentes do Remote Compose e RemoteModifier em vez dos equivalentes padrão do Compose. Eles incluem contêineres de layout básicos e componentes adaptáveis projetados especificamente para lidar com tamanhos de tela dinâmicos:

  • Componentes básicos de layout: elementos comuns de layout semelhantes ao Compose, como RemoteBox, RemoteRow e RemoteColumn.
  • Componentes de layout adaptáveis: componentes especializados, como RemoteFitBox, RemoteCollapsibleRow e RemoteCollapsibleColumn, projetados para se adaptar de forma limpa em superfícies remotas.
  • Temas do Material Design: os temas funcionam da mesma forma para widgets do Wear OS, com uma hierarquia de cores e tipografia fornecida por RemoteMaterialTheme. Isso permite uma implementação consistente de branding e sistema de design no app e nos widgets.

Desenho personalizado com RemoteCanvas

Para gráficos personalizados e animações baseadas em tempo, use RemoteCanvas, que registra comandos de desenho que o player executa no host. Este guia se concentra na criação de interfaces com componentes.

principais diferenças

Consulte os seguintes conceitos principais para entender como o Remote Compose gerencia estado, lógica e ações.

Referências de estado simbólico

No Compose padrão, os contêineres de estado mantêm valores ativos e legíveis na memória local do app, que são modificados pelo código do app (lambdas) quando algo acontece. No Remote Compose, as declarações de estado atuam como referências simbólicas. Em vez de manter valores ativos na memória local do app, elas declaram vinculações que o player remoto gerencia e atualiza localmente no momento da execução. Lembre-se das seguintes considerações ao declarar o estado no Remote Compose:

Estado remoto x fluxo de controle do Kotlin

O código Kotlin só é executado quando o app cria o documento. As instruções do Kotlin, como if, when e for, podem moldar o documento com base em valores conhecidos naquele momento, como repetir uma linha para cada item em uma lista, mas não podem reagir a um estado remoto que mude mais tarde. Lembre-se do seguinte ao trabalhar no Remote Compose:

  • Lógica de ramificação: a alternância dinâmica da interface é feita usando RemoteStateLayout, mapeando o estado para diferentes slots RemoteComposable.
  • Avaliação de texto: evite a interpolação de strings padrão do Kotlin ("$remoteValue"), que é avaliada apenas quando o documento é criado. Em vez disso, transmita RemoteString para RemoteText.

Estilo dinâmico usando RemoteModifier

A estilização dinâmica no host não executa novamente a composição. Em vez disso, as variáveis de estado remoto são transmitidas diretamente para modificadores, como RemoteModifier.background(remoteColor).

Contexto do sistema remoto

Os provedores CompositionLocal, como LocalConfiguration ou LocalDensity, refletem apenas o ambiente do app local no momento em que o documento é gravado. Eles não são atualizados dinamicamente no host remoto conforme a superfície é redimensionada, muda o estado de exibição ou avança no tempo. Em vez disso, use valores que o player resolve no host durante a execução, como o tamanho atual do componente, RemoteConfiguration ou RemoteDensity.

Ações declarativas

No Compose padrão, os gerenciadores de clique são lambdas que são executados no app. O host não pode executar o código do app. Portanto, no Remote Compose, você anexa ações, por exemplo, com RemoteModifier.clickable(action). Uma ação pode atualizar o estado remoto diretamente no host com valueChange ou transferir para o app ou o host com pendingIntentAction ou hostAction. Para executar várias ações com um clique, use combinedAction.

Comparação de paradigmas de alto nível

Domínio do recurso

Jetpack Compose padrão

Compose remoto

Eventos de clique e toque

Lambdas síncronas em processo

Objetos de ação serializados declarativos

Lógica condicional

Fluxo de controle "if" e "when" do Kotlin

O if/when padrão do Kotlin funciona normalmente para o estado estático conhecido ao gerar o documento.

A ramificação dinâmica usa RemoteStateLayout (para árvores de interface).

Loops de fluxo de controle

Loops "for" e "while" padrão do Kotlin

Os loops padrão do Kotlin (repeat, for, forEach) são executados apenas quando o documento é criado. Eles não podem fazer um loop no estado remoto no host

Host de execução

Processo do app

Acesso rápido (AppWidget), widgets do Wear OS ou qualquer formato com um player compatível

Ciclo de vida do processo

O processo precisa permanecer ativo para recompor e renderizar

Processa o documento de snapshot da IU de registros. O mecanismo do player remoto analisa a árvore de componentes, rastreia as mutações de estado e redesenha localmente sem chamar o app.

Efeitos colaterais

Ciclos de vida de corrotinas (LaunchedEffect)

Não disponível no host. A composição é executada no app para criar o documento. Portanto, os efeitos de corrotina não podem controlar a interface remota, a menos que a integração mantenha uma composição aberta.

Paradigma de estado

Valores de estado da memória local

Funções de fábrica (rememberMutableRemoteInt(), rememberNamedRemoteColor()) que retornam referências de estado simbólicas em vez de valores brutos.