L’équipe mobile de Savoir-faire Linux était à la DroidCon de New York, les 25 et 26 septembre derniers, l’événement dédié aux développeurs Android par excellence. Durant deux jours, plus de 900 participants sont venus assister à près de 70 conférences autour d’Android et son écosystème. Notre équipe mobile vous fait le point sur les présentations auxquelles elle a assisté.
Autour de l’architecture
Conférence “Model View Intent, Embracing reactive UI’S”
Nos développeurs Mobile sur place ! De gauche à droite : Alexandre Lision, Hadrien De Sousa et Thibault Wittemberg.
MVI est un motif de conception applicative tiré de la librairie javascript Cycle.js. Il repose avant tout sur les concept “d’Intents”, qui représentent le flux d’actions utilisateurs et sur la notion de “State”, qui représente l’état immutable de l’application à un instant T.
Les flux d’Intent sont branchés sur des “State Reducer”. Ces reducers sont de simples fonctions dont le but est de modifier l’état de l’application de proche en proche. Cet état est ensuite affiché par la vue sur la forme d’un “View State” (un état pré-formaté spécifiquement pour la vue devant l’afficher).
Ce motif de conception fait donc la part belle de la programmation réactive fonctionnelle. En cela, il est très proche de Redux et met en exergue l’intérêt de l’immutabilité de l’état (la mutabilité autorise le partage de référence sur des objets en mémoire, elle est donc source d’effets de bords non contrôlés).
Il permet également d’adresser la problématique récurrente de gestion du cycle de vie des Activity/Fragment en introduisant un cache de “State” sur lequel la vue va se brancher à chacune de ses instanciations (dans le cas d’une rotation par exemple).
Conférence “Reactive clean architecture”
L’idée de “Clean architecture” repose sur un découpage de l’application en 3 couches :
La programmation Reactive peut nous aider dans la communication entre ces couches que nous présentons ci-dessous.
Couche Data
Cette couche expose un “Repository” qui donne accès de façon publique à notre modèle de données et gère un “Reactive Store” qui maintient l’état de l’application. En interne, ce Repository s’appuiera sur des sous-couches techniques comme par exemple, les accès réseaux, la persistance et l’accès au système de fichiers.
Couche Domain
Cette couche s’appuie sur un “Reactive Interactor” dont le but sera de gérer les entrées utilisateur. Cet Interactor souscrit au “Reactive Store” afin d’en exposer (en les filtrant éventuellement) les états à destination des couches supérieures (notamment la couche Présentation).
Couche Présentation
Cette couche gère des “ViewEntities” qui représentent les états de l’application pré-formatées pour la vue. Un “View Model” se chargera de faire le mapping entre les états provenant du “Reactive Store” (mis à disposition par le “Reactive Interactor”) et ces “ViewEntities”.
Mot d’ouverture à la DroidConNY 2017
Conférence “Advanced networking with RX Java + Retrofit”
Les exemples d’utilisation de la librairie “Retrofit” ne permettent pas souvent de comprendre des cas complexes, tels que :
- la reprise sur échec
- la gestion des codes d’erreurs spécifiques
- l’affichage indicateur de progression
Voici, quelques pistes pour adresser chacun de ces cas :
Reprise sur échec
- Utiliser l’opérateur RxJava retryWhen.
Erreurs Http
Il peut être intéressant d’appliquer l’opérateur “share” sur l’observable Rx gérant les requêtes (cela permet de ne pas ré-exécuter la requêtes à chaque souscription). Il est ensuite possible de créer autant de souscriptions qu’il y a de code d’erreur à gérer, en appliquant à chacune de ses souscriptions un opérateur “filter” qui ne laissera passer que les résultats avec le code d’erreur à gérer.
Indicateur de progression
Le flux Rx gérant la requête réseau peut mettre un jour un “état de progression” sous la forme d’un “BehaviorSubject”. Le Presenter (ou ViewModel) peut ainsi s’abonner à l’Observable issue de ce Subject et donner lieu à une mise à jour de la vue.
Une astuce supplémentaire
Cela peut être intéressant d’utiliser RxLifeCycle, combiné au motif MVP pour faciliter la gestion des rotations.
Conférence sur Kotlin
“Full stack Kotlin”
Kotlin est un langage connu pour remplacer avantageusement Java, notamment en proposant une syntaxe plus efficace. Bien qu’associé à Android, il est aussi possible de l’utiliser dans de nombreux contextes comme : application serveur, application native, et application web.
Back-end
Ktor est une librairie proposée par Jetbrains (http://ktor.io). Elle permet de gérer la couche Http et les WebSockets. Il est donc tout à fait possible de développer une API Rest en Kotlin par exemple. Son fonctionnement est simple et passe par l’instantiation d’un serveur embarqué (Jetty, Netty ou Tomcat) puis par la définition de routes. Il est par ailleurs tout à fait possible de lui faire gérer la partie statique d’un site web. Son principal défaut réside dans son manque de documentation.
Les alternatives suivantes existent : Spring Boot / Javalin / Spark / Kara.
Front-end
Il est également possible d’écrire la partie front-end (HTML et javascript) d’un site internet en Kotlin grâce aux APIs suivantes:
- kotlin.browser
- kotlin.js
- kotlinx.html
Attention à bien utiliser le plugin gradle “kotlin2js” à la place du plugin “kotlin”.
Natif
Kotlin permet également d’écrire du code natif tout en ayant accès à toutes les fonctionnalités de Kotlin 1.1.
On pourra donc, au prix d’une compilation par type de plateforme, exécuter le même programme sur Mac Os, Linux, Android arm32/64, iOS et Windows. Bien sûr, cela ne concerne pas les interfaces utilisateurs puisque chaque système a ses particularités. Par ailleurs, on veillera à gérer correctement la mémoire à la façon d’un code en C.
Attention à bien utiliser le plugin gradle “konan” à la place du plugin “kotlin”.
Build
Kobalt est un système de build inspiré de Gradle et Maven. Il est entièrement écrit en Kotlin et ses fichiers de compilation sont également des fichiers Kotlin valides, il est donc possible de bénéficier des fonctionnalités d’auto-complétion de code offerte par les IDE.
“Data binding in a Kotlin world”
Le Databinding tel que proposé par Google se marie bien avec :
- Dagger
- RxJava
- Kotlin
- Architecture Components
- Butterknife
Il est cependant incompatible avec :
Il est possible d’utiliser un langage d’expression directement dans le layout XML (pour faire du traitement conditionnel, des opérateurs mathématiques, etc.). Cette pratique est peu répandue puisqu’elle brise les principes de responsabilité, à savoir écrire du code métier dans la partie vue.
Autour de l’expérience UI/UX
Conférence “View performance deep dive”
Les équipes de Facebook tentent d’apporter une solution aux problèmes potentiels de performance dans le rendu des vues, plus particulièrement au niveau de l’affichage des listes (ListViews, RecyclerViews…).
Pour ce faire, ils ont établi un comparatif en 3 étapes, en mesurant les performances de rendu des vues avec l’outil “Systrace” de Google sur un Nexus 5.
Etape 1 : RecyclerView avec ConstraintLayout
Chaque cellule de la liste est basée sur un layout de type “Constraint Layout”. Les cellules sont relativement simples et ne contiennent qu’un champ texte, un bouton et une image.
L’analyse des performances montre que le système omet certaines frames et donc, ne propose pas un rendu optimal.
Retour d’expérience sur les Constraint Layout dans un recyclerView : le wrap_content est parfois mal interprété sur la hauteur des ViewHolders ce qui oblige à utiliser une hauteur fixe.
Etape 2 : RecyclerView avec Drawable
L’idée ici n’est pas de construire une arborescence de vue au sein d’une cellule, mais de la dessiner sous forme d’un Drawable unique.
La vue racine de la cellule expose donc son Canvas, sur lequel on va venir dessiner nos composants. Cette technique demande énormément de ré-écriture de code et ne prend pas en compte les APIs d’accessibilité ou encore les évènements de type Touch.
La mesure avec Systrace nous indique un gain évident en matière de rendu.
Etape 3 : Litho
Litho est une librairie mise à disposition par Facebook. Elle repose sur l’aspect déclaratif des composants graphiques directement dans le code, et non dans des layouts XML.
Son objectif premier est de réduire le temps de calcul du rendu de la vue. Pour cela, elle se base sur :
- un découpage plus fin de l’arborescence de vues (ne redessine que ce qui est affiché),
- un rendu global de la vue sous forme d’un Drawable,
- le calcul du rendu dans un “background thread”.
Elle gère par ailleurs les API d’accessibilité et bien sûr les évènements de type Touch. Facebook travaille actuellement à l’intégration des animations customs.
Facebook nous montre clairement son intention de faire converger les notions mises en avant dans React.js avec la programmation par Composant et l’utilisation des Props et des State. Le moteur interne de Litho se chargeant de mimer le comportement d’un DOM virtuel. C’est une vision concurrente de modélisation de type MVVM, MVP ou MVI, où l’on tendra à utiliser en complément des layouts XML un binding de données (Binding standard d’Android ou RxBinding).
Doze
Inclus depuis Android Marshmallow (API 26), Doze et App Standby sont deux composants d’économie d’énergie. Doze est un mode système qui restreint l’accès aux services, les applications utilisant intensivement le CPU et le réseau.
Depuis Android Oreo (API 26), ces restrictions sont encore plus sévères et désactivent même les broadcasts implicites et il n’est plus possible de démarrer un service dans une application en arrière-plan.
Pour faciliter la migration des applications pour inclure ces nouvelles restrictions, Evernote a mis en place la librairie android-job permettant la création de jobs en différés et en arrière-plan.
Conférence “The Resurgence of SQL”
Après un passage de mode et tandis que de nombreuses librairies d’ORM permettent de s’en abstraire, le SQL revient aujourd’hui avec SQLDelight et Room.
Correctement utilisé, SQL permet d’exécuter du métier directement dans la base de donnée plutôt que dans le code afin de gagner en performance.
SQLDelight
Cette librairie développée par Square génère des modèles Java depuis du SQL qui permettent de lire et d’écrire dans la base de donnée. Les tables et déclarations SQL sont écrits directement dans des fichiers .sq interprété par la librairie.
SQLDelight supporte AutoValue mais ne supporte pas les data class Kotlin dans sa version actuelle
Room
Room est une couche d’abstraction de SQLite développé par Google pour Android et fait partie des Architecture Components tels que LiveData et ViewModel.
Cette librairie génère du SQL à partir du Java à l’aide d’annotation pré-processeur.
On trouve de nombreux exemples d’implémentation de cette librairie notamment en Kotlin et il existe une documentation plus complète que pour SQLDelight.
Consultez la documentation de Room sur Android Developers.
Conférence “GraphQL on Android is here!”
GraphQL
GraphQL est un langage de requête pour le développement d’API dont le but est de fournir une description complète des données permettant aux clients de requêter uniquement ce dont ils ont besoin. GraphQL est développé par Facebook et se veut une réponse aux problèmes rencontrés lors du développement d’API Rest.
Apollo
Apollo-Android est un client GraphQL qui génère des modèles Java à partir de requêtes GraphQL écritent dans un fichier .graphql. Les classes générées permettent de créer les requêtes réseaux vers l’API GraphQL.
Apollo a été écrit dans le but d’être pleinement compatible avec la librairie de programmation réactive RxJava2.
Conférence “Upgrading to Moshi”
Moshi est une librairie de parsing de JSON vers Java développé par Square qui se veut le successeur de Gson jugé inactif et lourd (1345 méthodes pour Gson contre 759 pour Moshi).
L’implémentation de Moshi est relativement similaire à celle de Gson afin de faciliter la migration de l’un à l’autre. Quelques différences cependant :
- Moshi intègre moins d’adaptateur par défaut pour les types plateformes Java et Android, ce qui oblige le développeur à écrire ses propres adaptateurs
- Dans un but de simplification, Moshi est moins configurable (pas de stratégie de nommage, versioning, etc.)
- Pas de JsonElement
- Moshi utilise la libraire Okio pour l’I/O et s’intègre parfaitement avec OKHttp
Moshi supporte également Kotlin (moshi-kotlin) mais est dépendante dans sa version actuelle de kotlin-reflect donc la taille est très importante pour les standards Android (11,500 méthodes).