Plongez dans Jetpack Compose

Bonjour à tous. Avant de partir pour le week-end, nous nous empressons de partager avec vous une autre traduction préparée spécialement pour les étudiants du développeur Android. Cours avancé . "



Essayer un nouveau cadre d'interface utilisateur pour les applications Android


Au cours des dernières années, participant à de nombreux projets mobiles, j'ai dû utiliser diverses technologies, telles que Android, ReactNative et Flutter. Passer de ReactNative à Android classique m'a fait des sentiments mitigés. Le retour à Kotlin s'est bien passé, mais j'ai vraiment manqué le framework React UI. Les petits composants réutilisables qui composent l'interface utilisateur sont excellents et offrent plus de flexibilité et de rapidité de développement.

De retour dans Android classique, je devais m'inquiéter de garder la hiérarchie des vues aussi uniforme que possible. De ce fait, il est difficile de se consacrer véritablement à l'approche composante. Cela rend le copier-coller plus attrayant, ce qui conduit à un code plus complexe et moins pris en charge. En fin de compte, nous nous gardons d'expérimenter avec une interface utilisateur qui pourrait améliorer l'UX.


Android révèle Jetpack Compose. Illustration: Emanuel Bagilla

Jetpack Compose à la rescousse


Par conséquent, après avoir regardé les nouveautés d'Android lors de la conférence Google I / O 2019, j'ai immédiatement commencé à traiter avec Compose et j'ai essayé d'en savoir plus. Compose est une boîte à outils d'interface utilisateur réactive entièrement développée par Kotlin. Compose ressemble beaucoup aux frameworks d'interface utilisateur existants tels que React, Litho ou Flutter.

La structure actuelle du cadre de l'interface utilisateur Android existe depuis 2008, et au fil du temps est devenue plus complexe, elle est assez difficile à maintenir. Jetpack Compose vise à partir du début, en tenant compte de la philosophie des composants modernes. Le cadre est rédigé en gardant à l'esprit les principaux objectifs suivants:

  • Incohérence avec les versions de la plate-forme: cela vous permet de corriger rapidement les bogues, car Compose ne dépend pas des nouvelles versions d'Android.
  • Pile technologique plus petite: le framework ne vous oblige pas à utiliser View ou Fragment lors de la création d'une interface utilisateur. Tous les éléments sont des composants et peuvent être librement composés ensemble.
  • Gestion transparente des états et gestion des événements: l' une des choses les plus importantes et les plus complexes que vous devez résoudre dans les grandes applications est le traitement du flux de données et de l'état dans votre interface utilisateur. Compose précise qui est responsable de l'état et comment les événements doivent être gérés, de la même manière que React le gère.
  • Écrire moins de code: l' écriture d'une interface utilisateur dans Android nécessite généralement beaucoup de code, en particulier lors de la création de mises en page plus complexes, par exemple, à l'aide de RecyclerView. Compose vise à simplifier considérablement la façon de créer une interface utilisateur.

Cela facilite la création de composants isolés et réutilisables, ce qui facilite la création d'un nouvel écran avec des éléments existants. Vous aider, en tant que développeur, à vous concentrer sur la création d'une interface utilisateur pratique, au lieu d'essayer de contrôler la hiérarchie des vues et d'apprivoiser la vue et le fragment.

Une application simple avec Compose: Hello World


Jetons un coup d'œil au code d'une application Hello World simple avec Jetpack Compose.

class ComposeActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { MyApp() } } } @Composable fun MyApp() { MaterialTheme { Text(text = "Hello world!", style = +themeTextStyle { h3 }) } } } 

Dans la méthode onCreate nous définissons le contenu de notre application en appelant setContent . Il s'agit d'une méthode qui initialise une arborescence de widgets composites et l'enveloppe dans un FrameLayout .

Pour que cela fonctionne, nous devons envelopper notre application dans CraneWrapper et MaterialTheme . CraneWrapper est responsable de la configuration des fournisseurs pour Context , FocusManager et TextInputService . MaterialTheme nécessaire pour fournir les couleurs, les styles et les polices de vos widgets. Dans cet esprit, nous pouvons ajouter le composant Text , qui affichera notre texte à l'écran dans un certain style.

Introduction de l'état


La gestion du flux de données et des états peut être une tâche ardue. Pour illustrer la simplicité de Compose, créons une application de compteur simple.
Pour travailler avec des états, Jetpack Compose utilise les idées d'autres frameworks d'interface utilisateur modernes, tels que Flutter et React. Il existe un flux de données unidirectionnel et réactif qui entraîne la mise à jour ou la «reconstruction» de votre widget.

 @Composable fun MyApp() { MaterialTheme { Counter() } } @Composable fun Counter() { val amount = +state { 0 } Column { Text(text = "Counter demo") Button(text = "Add", onClick = { amount.value++ }) Button(text = "Subtract", onClick = { amount.value-- }) Text(text = "Clicks: ${amount.value}") } } 


Dans l'exemple ci-dessus, nous ajoutons les boutons «Ajouter» et «Soustraire» ainsi qu'une étiquette qui affiche le nombre actuel de clics. Comme vous pouvez le voir dans l'exemple ci-dessous, en mettant à jour l'état «montant», les widgets sont intelligemment réorganisés lorsque l'état change.


Lancer une application de démonstration

L'état de amount est initialisé avec +state { 0 } . En essayant de comprendre quel genre de sorcellerie est, j'ai rampé dans le code source. C'est mon avis, même si je ne suis toujours pas sûr de tout comprendre.

state {...} crée un Effect< State < T < code>> . La classe Effect est une classe floue qui contient un bloc de code exécutable qui s'exécute de manière positionnelle dans le contexte d'une composition. La classe State contient une valeur avec le type Model , ce qui rend essentiellement cette valeur observable. L'opérateur + est un opérateur temporaire qui résout l' State de l' Effect .

Modèles d'état personnalisés


Au lieu d'utiliser +state {} pour créer un modèle à valeur unique, nous pouvons également créer un modèle personnalisé à l'aide de l'annotation @Model. Nous pouvons améliorer notre application de compteur en la divisant en petits widgets et en passant le modèle à d'autres widgets qui sont mis à jour et affichent l'état de ce modèle.

 @Model class CounterModel { var counter: Int = 0 var header = "Counter demo" fun add() { counter++ } fun subtract() { counter-- } } 


En utilisant l'annotation @Model , le plugin Compose Compiler rend toutes les variables de votre modèle observables afin qu'elles puissent être utilisées pour réorganiser les widgets. Mettons à jour notre widget pour utiliser CounterModel :

 @Composable fun Counter(counterModel: CounterModel) { Column { CounterHeader(counterModel) AddSubtractButtons(counterModel) CounterLabel(counterModel) } } @Composable fun CounterHeader(counterModel: CounterModel) { Text(text = counterModel.header) } @Composable fun AddSubtractButtons(counterModel: CounterModel) { Button( text = "Add", onClick = { counterModel.add() }) Button( text = "Subtract", onClick = { counterModel.subtract() }) } @Composable fun CounterLabel(counterModel: CounterModel) { Text(text = "Clicks: ${counterModel.counter}") } 


Le seul widget constitué par l'application spinner est désormais divisé en plusieurs widgets composables plus petits. CounterModel est transmis à divers widgets, soit pour afficher l'état du modèle, soit pour changer l'état du modèle à l'aide des fonctions add() ou subtract() .

Plus de vue


Il est important de comprendre que les widgets Jetpack Compose n'utilisent pas de vue ou de fragment sous le capot, ce sont juste les fonctions qui dessinent sur le canevas. Le plugin Compose Compiler traite toutes les fonctions avec l'annotation @Composable et met automatiquement à jour la hiérarchie de l'interface utilisateur.

Par exemple, un widget Divider compose d'un widget Padding qui contient un widget DrawFillRect . En regardant le code source de DrawFillRect , il devient clair qu'il dessine des lignes directement sur la toile. Tous les autres widgets sont implémentés de la même manière.

 @Composable private fun DrawFillRect(brush: Brush) { Draw { canvas, parentSize -> val paint = Paint() brush.applyBrush(paint) canvas.drawRect(parentSize.toRect(), paint) } } 


Le code source du DrawFillRect utilisé dans le widget Divider.
Si nous regardons l'inspecteur de mise en page en lançant l'un des exemples d'applications de Google, nous verrons clairement que lors du lancement de l'application Android avec Compose, il n'y a ni View ni ViewGroups . Nous voyons un FrameLayout contenant le CraneWrapper que nous avons créé dans le code, à partir de là, la hiérarchie de l'interface utilisateur de composition est affichée à l'écran.


L'inspecteur de mise en page inspecte Jetpack Compose.

L'absence de vues signifie également que Jetpack Compose ne peut pas utiliser les vues actuellement disponibles, telles que android.widget.Button , et doit créer tous les widgets à partir de zéro. Si vous regardez, par exemple, Flutter, qui utilise la même approche, vous pouvez voir que c'est un travail difficile. C'est l'une des raisons pour lesquelles Jetpack Compose aura besoin de temps avant d'être prêt à être utilisé en production.

Tous les éléments sont des widgets.


Tout comme Flutter, dans Compose tous les éléments sont des widgets. Des widgets plus complexes ont été décomposés en widgets élémentaires avec des responsabilités claires. Par conséquent, même le rembourrage, les espaceurs, etc. sont des widgets. Par exemple, si vous souhaitez ajouter une indentation autour d'un bouton, enveloppez-le simplement dans le widget de remplissage:

 Padding(padding = 16.dp) { Button(text = "Say hello", onClick = { ... }) } 


Connexion du code à l'interface utilisateur


La combinaison de code Kotlin avec des widgets d'interface utilisateur est très facile. Par exemple, si vous souhaitez afficher une interface utilisateur qui se répète ou dépend de certaines conditions. Ainsi, vous pouvez facilement afficher une liste de noms, comme indiqué ci-dessous.

 Column { listOf("John", "Julia", "Alice", "Mark").forEach { Text(text = it) } } 


C'est une fonctionnalité vraiment puissante, mais vous devez faire attention à ne pas programmer trop de logique au niveau de l'interface utilisateur.

Compatible avec vos applications Android


Compose est conçu pour que vous puissiez l'ajouter à une application existante et transférer progressivement certaines parties de votre interface utilisateur vers un nouveau cadre. Les exemples ci-dessus ajoutent l'interface utilisateur Jetpack Compose à une activité. Vous pouvez également incorporer des widgets Composer dans une présentation XML existante à l'aide de l'annotation GenerateView :

 @Composable @GenerateView fun Greeting(name: String) { /* … */ } //  -  layout.xml <GreetingView app:name=”John” /> 

Conclusion


Je suis ravi de Compose, car il réduit la souffrance croissante que je ressens lors du développement pour Android. Il permet d'être plus flexible, de se concentrer sur la création d'une interface utilisateur pratique et une responsabilité claire permet également d'éviter les erreurs.

Compose a un long chemin à parcourir, à mon avis, il peut être utilisé en production au plus tôt dans un an ou deux. Cependant, je pense que c'est le bon moment pour jeter un œil au Jetpack Compose. Les créateurs recherchent activement des commentaires, à ce stade, vous pouvez toujours apporter des modifications. Tous les avis contribueront à améliorer ce nouveau cadre.

Lisez mon article Try Jetpack Compose aujourd'hui pour savoir comment brancher la pré-alpha de Compose. De plus, je pense qu'il sera très intéressant pour vous de regarder une vidéo sur les modèles d'interface déclarative avec Google I / O.
J'ai hâte de pouvoir utiliser Compose dans de vraies applications Android!

C’est tout. Nous attendons vos commentaires avec impatience et nous vous souhaitons un excellent week-end!

Source: https://habr.com/ru/post/fr458106/


All Articles