Concepts et architecture de Remote Compose

Remote Compose est une bibliothèque Jetpack qui vous permet de créer une UI avec des API de style Compose dans votre application et de l'afficher dans les processus système, tels que les widgets d'application ou les widgets Wear OS. Votre application enregistre l'UI sous la forme d'un document compact, et un lecteur du processus hôte l'affiche et gère les interactions, les changements d'état et les animations localement, sans rappeler votre application.

Ce guide explique l'architecture de Remote Compose et en quoi elle diffère de celle de Jetpack Compose standard. Ce guide explique comment créer une UI avec des composants.

Cas d'utilisation de Remote Compose

Remote Compose peut être utilisé sur n'importe quelle surface avec un lecteur compatible. Sur Android, il permet de créer des widgets d'application et des widgets Wear OS.

Fonctionnement : architecture à trois blocs

La différence architecturale fondamentale entre Remote Compose et Jetpack Compose standard réside dans le découplage de la définition de l'UI de l'exécution sur trois blocs de haut niveau :

  • Créer le document : votre application exécute vos fonctions @RemoteComposable pour enregistrer un document, c'est-à-dire une description compacte et sérialisée de l'UI, y compris sa mise en page, son état distant et ses actions. Lorsque vos données changent, votre application peut enregistrer et envoyer un nouveau document.
  • Transporter le document vers l'hôte distant : votre application transmet le document à l'hôte, le processus qui l'affiche, tel qu'un lanceur d'applications ou Wear OS.
  • Lire le document : un lecteur Remote Compose dans l'hôte affiche le document et gère la mise en page, la saisie, les changements d'état de l'expérience utilisateur et les animations localement, sans rappeler votre application.

Cette architecture offre des avantages majeurs qui réduisent directement la latence :

  • Petite taille de document : les instantanés de document sérialisés restent compacts et légers.
  • Allers-retours réduits : étant donné que le lecteur hôte distant gère les interactions et les changements d'état localement, les communications aller-retour vers l'application ou le serveur sont réduites au minimum.

Analogie avec une page Web/HTML : Remote Compose fonctionne de la même manière que la diffusion d'une page Web. Le serveur d'applications génère et envoie une structure HTML/document une seule fois, et l'hôte du navigateur l'affiche et gère les interactions localement sans interroger constamment le backend.

Communication entre le processus de l'application et le processus de l'hôte distant pour Remote Compose
Figure 1. Les trois blocs de l'architecture Remote Compose

Composants

Remote Compose fournit des composants d'interface utilisateur de haut niveau pour structurer les mises en page. Utilisez les composants Remote Compose et RemoteModifier au lieu de leurs équivalents Compose standards. Il s'agit de conteneurs de mise en page de base, ainsi que de composants adaptatifs spécialement conçus pour gérer les tailles d'écran dynamiques :

  • Composants de mise en page de base : éléments de mise en page courants de type Compose, tels que RemoteBox, RemoteRow et RemoteColumn.
  • Composants de mise en page adaptative : composants spécialisés tels que RemoteFitBox, RemoteCollapsibleRow et RemoteCollapsibleColumn conçus pour s'adapter parfaitement aux surfaces distantes.
  • Thématisation Material Design : la thématisation fonctionne de la même manière pour les widgets Wear OS, avec une hiérarchie de couleurs et de typographies fournie par RemoteMaterialTheme. Cela permet d'implémenter un branding et un système de conception cohérents dans votre application et vos widgets.

Dessin personnalisé avec RemoteCanvas

Pour les graphismes personnalisés et les animations temporelles, utilisez RemoteCanvas, qui enregistre les commandes de dessin que le lecteur exécute sur l'hôte. Ce guide se concentre sur la création d'interfaces utilisateur avec des composants.

Différences majeures

Consultez les concepts de base suivants pour comprendre comment Remote Compose gère l'état, la logique et les actions.

Références d'état symboliques

Dans Compose standard, les conteneurs d'état contiennent des valeurs actives et lisibles dans la mémoire locale de l'application, qui sont modifiées par le code de l'application (lambdas) lorsque des événements se produisent. Dans Remote Compose, les déclarations d'état agissent comme des références symboliques. Au lieu de conserver les valeurs actives dans la mémoire locale de l'application, ils déclarent des liaisons que le lecteur distant gère et met à jour localement au moment de l'exécution. Tenez compte des points suivants lorsque vous déclarez un état dans Remote Compose :

  • Utilisez les fonctions d'usine Remote Compose pour déclarer un état tel que rememberMutableRemoteInt, rememberMutableRemoteFloat ou rememberMutableRemoteString.
  • Le code de votre application ne peut pas inspecter ni lire directement la valeur d'une variable d'état distante pendant la composition.
  • Le lecteur stocke et met à jour ces valeurs localement lorsque l'utilisateur interagit avec le document.

État distant et flux de contrôle Kotlin

Votre code Kotlin ne s'exécute que lorsque votre application crée le document. Les instructions Kotlin telles que "if", "when" et "for" peuvent mettre en forme le document en fonction des valeurs connues à ce moment-là, par exemple en répétant une ligne pour chaque élément d'une liste, mais elles ne peuvent pas réagir à un état distant qui change ultérieurement. Tenez compte des points suivants lorsque vous travaillez dans Remote Compose :

  • Logique de branchement : le changement d'UI dynamique s'effectue à l'aide de RemoteStateLayout en mappant l'état à différents emplacements RemoteComposable.
  • Évaluation du texte : évitez l'interpolation de chaîne Kotlin standard ("$remoteValue"), qui n'est évaluée que lors de la création du document. Transmettez plutôt RemoteString à RemoteText.

Style dynamique avec RemoteModifier

Le style dynamique sur l'hôte ne réexécute pas la composition. À la place, les variables d'état distantes sont transmises directement aux modificateurs, tels que RemoteModifier.background(remoteColor).

Contexte de systèmes distants

Les fournisseurs CompositionLocal tels que LocalConfiguration ou LocalDensity ne reflètent l'environnement de l'application locale qu'au moment de l'enregistrement du document. Ils ne sont pas mis à jour de manière dynamique sur l'hôte distant lorsque la surface est redimensionnée, change d'état d'affichage ou avance dans le temps. Utilisez plutôt des valeurs que le lecteur résout sur l'hôte au moment de l'exécution, telles que la taille actuelle du composant, RemoteConfiguration ou RemoteDensity.

Actions déclaratives

Dans Compose standard, les gestionnaires de clics sont des lambdas qui s'exécutent dans votre application. L'hôte ne peut pas exécuter le code de votre application. Par conséquent, dans Remote Compose, vous associez des actions à la place, par exemple avec RemoteModifier.clickable(action). Une action peut mettre à jour l'état distant directement sur l'hôte avec valueChange, ou transmettre l'état à votre application ou à l'hôte avec pendingIntentAction ou hostAction. Pour exécuter plusieurs actions en un seul clic, utilisez combinedAction.

Comparaison des paradigmes de haut niveau

Domaine de la fonctionnalité

Jetpack Compose standard

Remote Compose

Événements de clic et tactiles

Lambdas synchrones en cours de processus

Objets Action sérialisés déclaratifs

Logique conditionnelle

Flux de contrôle "if" et "when" en Kotlin

La fonction if/when Kotlin standard fonctionne normalement pour l'état statique connu lors de la génération du document.

La ramification dynamique utilise RemoteStateLayout (pour les arborescences d'UI).

Boucles de flux de contrôle

Boucles Kotlin standards "for" et "while"

Les boucles Kotlin standards (repeat, for, forEach) ne s'exécutent que lors de la création du document. Ils ne peuvent pas effectuer de boucle sur l'état distant sur l'hôte.

Hôte d'exécution

Processus de l'application

Lanceur d'applications (AppWidget), widgets Wear OS ou tout facteur de forme avec un lecteur compatible

Cycle de vie des processus

Le processus doit rester actif pour recomposer et afficher

Le moteur Remote Player analyse l'arborescence des composants, suit les mutations d'état et redessine l'UI localement sans rappeler l'application.

Effets secondaires

Cycles de vie des coroutines (LaunchedEffect)

Non disponible sur l'hôte. La composition s'exécute dans votre application pour créer le document. Par conséquent, les effets de coroutine ne peuvent pas piloter l'UI distante, sauf si l'intégration maintient une composition ouverte.

Paradigme d'état

Valeurs d'état de la mémoire locale

Fonctions d'usine (rememberMutableRemoteInt(), rememberNamedRemoteColor()) qui renvoient des références d'état symboliques plutôt que des valeurs brutes.