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
@RemoteComposablepara 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.
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,RemoteRowyRemoteColumn. - Componentes de diseño adaptables: Son componentes especializados, como
RemoteFitBox,RemoteCollapsibleRowyRemoteCollapsibleColumn, 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,rememberMutableRemoteFloatorememberMutableRemoteString. - 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
RemoteStateLayoutasignando el estado a diferentes ranuras deRemoteComposable. - 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, pasaRemoteStringaRemoteText.
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 La ramificación dinámica usa |
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 |