Conceptos y arquitectura de Remote Compose

Remote Compose es una biblioteca de Jetpack que te permite compilar la IU con APIs de estilo de Compose en tu app y mostrarla en procesos del sistema, como widgets de apps o de Wear OS. Tu app registra la IU como un documento compacto, y un reproductor en el proceso del host la renderiza y controla las interacciones, los cambios de estado y las animaciones de forma local, sin volver a llamar a tu app.

En esta guía, se explica la arquitectura de Remote Compose y en qué se diferencia de Jetpack Compose estándar. Esta guía se enfoca en la compilación de IU con componentes.

Casos de uso de Remote Compose

Remote Compose se puede usar en cualquier plataforma con un reproductor compatible. En Android, potencia los widgets de apps y los widgets de Wear OS.

Cómo funciona: Arquitectura de tres bloques

La distinción arquitectónica fundamental entre Remote Compose y Jetpack Compose estándar radica en separar la definición de la IU de la ejecución en tres bloques de alto nivel:

  • Crea el documento: Tu app ejecuta tus funciones @RemoteComposable para registrar un documento: una descripción compacta y serializada de la IU, incluidos su diseño, estado remoto y acciones. Cuando tus datos cambian, tu app puede registrar y enviar un documento nuevo.
  • Transportar el documento al host remoto: Tu app pasa el documento al host, el proceso que lo muestra, como un selector o Wear OS.
  • Reproduce el documento: Un reproductor de Remote Compose en el host renderiza el documento y controla el diseño, la entrada, los cambios de estado de la UX y las animaciones de forma local, sin volver a llamar a tu app.

Esta arquitectura proporciona beneficios principales que reducen directamente la latencia:

  • Tamaño de documento pequeño: Las instantáneas de documentos serializados siguen siendo compactas y livianas.
  • Menos viajes de ida y vuelta: Debido a que el reproductor de host remoto controla la interacción y los cambios de estado de forma local, se minimizan las comunicaciones de ida y vuelta a la aplicación o al servidor.

Analogía de página web/HTML: Remote Compose funciona de manera similar a la publicación de una página web. El servidor de la app genera y envía una estructura de documento o HTML una vez, y el host del navegador la renderiza y controla las interacciones de forma local sin consultar constantemente el backend.

Comunicación del proceso de la app con el proceso del host remoto para Remote Compose
Figura 1: Los tres bloques de la arquitectura de Remote Compose

Componentes

Remote Compose proporciona componentes de IU de alto nivel para estructurar diseños. Usa los componentes de Remote Compose y RemoteModifier en lugar de sus equivalentes estándar de Compose. Estos incluyen contenedores de diseño básicos, así como componentes adaptables diseñados específicamente para controlar tamaños de pantalla dinámicos:

  • Componentes de diseño básicos: Son elementos de diseño comunes similares a Compose, como RemoteBox, RemoteRow y RemoteColumn.
  • Componentes de diseño adaptables: Son componentes especializados, como RemoteFitBox, RemoteCollapsibleRow y RemoteCollapsibleColumn, diseñados para adaptarse de forma clara en las plataformas remotas.
  • Temas de Material Design: Los temas funcionan de la misma manera para los widgets de Wear OS, con una jerarquía de color y tipografía proporcionada por RemoteMaterialTheme. Esto permite una implementación coherente de la marca y del sistema de diseño en tu app y tus widgets.

Dibujo personalizado con RemoteCanvas

Para gráficos personalizados y animaciones basadas en el tiempo, usa RemoteCanvas, que registra los comandos de dibujo que el reproductor ejecuta en el host. Esta guía se enfoca en la compilación de la IU con componentes.

Diferencias clave

Revisa los siguientes conceptos básicos para comprender cómo Remote Compose administra el estado, la lógica y las acciones.

Referencias de estado simbólicas

En Compose estándar, los contenedores de estado contienen valores activos y legibles en la memoria local de la app que el código de la app (lambdas) muta cuando ocurren eventos. En Remote Compose, las declaraciones de estado actúan como referencias simbólicas. En lugar de mantener valores activos en la memoria local de la app, declaran vinculaciones que el reproductor remoto administra y actualiza de forma local durante el tiempo de ejecución. Ten en cuenta las siguientes consideraciones cuando declares el estado en Remote Compose:

  • Usa las funciones de fábrica de Remote Compose para declarar estados, como rememberMutableRemoteInt, rememberMutableRemoteFloat o rememberMutableRemoteString.
  • El código de tu app no puede inspeccionar ni leer el valor de una variable de estado remota directamente durante la composición.
  • El reproductor almacena y actualiza estos valores de forma local a medida que el usuario interactúa con el documento.

Estado remoto frente al flujo de control de Kotlin

Tu código Kotlin se ejecuta solo cuando la app crea el documento. Las sentencias de Kotlin, como if, when y for, pueden dar forma al documento según los valores conocidos en ese momento, como repetir una fila para cada elemento de una lista, pero no pueden reaccionar a un estado remoto que cambie más adelante. Ten en cuenta lo siguiente cuando trabajes en Remote Compose:

  • Lógica de ramificación: El cambio dinámico de la IU se realiza con RemoteStateLayout asignando el estado a diferentes ranuras de RemoteComposable.
  • Evaluación de texto: Evita la interpolación de cadenas estándar de Kotlin ("$remoteValue"), que se evalúa solo cuando se crea el documento. En su lugar, pasa RemoteString a RemoteText.

Estilo dinámico con RemoteModifier

El diseño dinámico en el host no vuelve a ejecutar la composición; en su lugar, las variables de estado remoto se pasan directamente a los modificadores, como RemoteModifier.background(remoteColor).

Contexto del sistema remoto

Los proveedores de CompositionLocal, como LocalConfiguration o LocalDensity, solo reflejan el entorno de la app local en el momento en que se graba el documento. No se actualizan de forma dinámica en el host remoto a medida que cambia el tamaño de la superficie, cambia el estado de la pantalla o avanza el tiempo. En su lugar, usa valores que el reproductor resuelva en el host durante el tiempo de ejecución, como el tamaño actual del componente, RemoteConfiguration o RemoteDensity.

Acciones declarativas

En Compose estándar, los controladores de clics son lambdas que se ejecutan en tu app. El host no puede ejecutar el código de tu app, por lo que, en Remote Compose, debes adjuntar acciones, por ejemplo, con RemoteModifier.clickable(action). Una acción puede actualizar el estado remoto directamente en el host con valueChange, o bien transferirlo a tu app o al host con pendingIntentAction o hostAction. Para ejecutar varias acciones con un solo clic, usa combinedAction.

Comparación de paradigmas de alto nivel

Dominio de funciones

Jetpack Compose estándar

Compose remoto

Eventos de clic y táctiles

Lambdas síncronas en proceso

Objetos Action serializados declarativos

Lógica condicional

Flujo de control if y when de Kotlin

El if/when estándar de Kotlin funciona normalmente para el estado estático conocido cuando se genera el documento.

La ramificación dinámica usa RemoteStateLayout (para árboles de IU).

Bucles de flujo de control

Bucles for y while estándar de Kotlin

Los bucles estándar de Kotlin (repeat, for, forEach) se ejecutan solo cuando se crea el documento. No pueden realizar bucles sobre el estado remoto en el host.

Host de ejecución

Proceso de la app

Selector (AppWidget), widgets de Wear OS o cualquier factor de forma con un reproductor compatible

Ciclo de vida de los procesos

El proceso debe permanecer activo para recomponer y renderizar

Procesa el documento de instantánea de la IU de los registros; el motor de Remote Player analiza el árbol de componentes, hace un seguimiento de las mutaciones de estado y vuelve a dibujar de forma local sin volver a llamar a la app.

Efectos secundarios

Ciclos de vida de las corrutinas (LaunchedEffect)

No está disponible en el host. La composición se ejecuta en tu app para crear el documento, por lo que los efectos de corrutina no pueden controlar la IU remota, a menos que la integración mantenga abierta una composición.

Paradigma de estado

Valores de estado de la memoria local

Funciones de fábrica (rememberMutableRemoteInt(), rememberNamedRemoteColor()) que devuelven referencias de estado simbólicas en lugar de valores sin procesar