L'objectif de cet exercice est d'implémenter de façon incrémentale une application Android qui s'apparente à un Instagram avec des photos de chien. Ce développement va permettre d'acquérir des bonnes pratiques de code et de découvrir ou de consolider les connaissances en :
- Clean Archi : couches presentation, domain et data et injection de dépendance
- tests unitaires : avec Junit et Mockito
- gestion des flux de données : Coroutine et Flow
- gestion de la vue : vue XML classique et Jetpack Compose
ChienStagram est une application Android donc le front-end qui permet d'afficher une liste de posts de chien, c'est-à-dire une photo d'un chien (ou chat) postée par une utilisateur, à une certaine date, avec une description et des tags. Chaque utilisateur peut en outre liker et laisser un commentaire sur un post.
Dans l'univers de ChienStagram, la RGPD n'existe pas. Chaque utilisateur a un prénom, nom, genre, date de naissance, e-mail, téléphone et adresse physique.
ChienStagram est découpé en 3 écrans principaux :
- L'écran d'accueil : home screen qui contient la liste des posts
- L'écran de post : post screen qui permet de visualiser l'image en grand et le détail d'un post. Il est accessible au clic sur un post depuis l'écran d'accueil
- L'écran de profil : user screen où l'on peut voir les informations de l'utilisateur. Il est accessible par un clic sur n'importe quel avatar sur les deux précédents écrans.
Voici un exemple d'interface pour l'application. Il est possible de changer les formes, les tailles, les couleurs ou faire apparaîte des informations de différentes manières ou de les masquer :
home screen | post screen | user screen |
---|---|---|
L'architecture du projet a été mis en place et le premier écran a été développé. L'objectif est de développer les deux autres écrans en commençant par la couche domain, puis data et enfin présentation.
Avant de commencer les développements il est conseillé de s'impreigner du code (ne pas hésiter à avoir un oeil critique dessus) et de lire ces liens si vous en ressentez le besoin :
- Un Article Medium sur la Clean Archi Android
- La doc Android sur les fondamentaux du testing
- La doc Android sur les Coroutines et les Flow
L'application repose sur dummyAPI dont la documentation est disponible ici. Il faut se créer un compte et générer une app-id comme indiqué dans la page Getting Started. Cette app-id est à mettre dans la classe DummyApi
du module :api
.
Avant de se lancer il faut avoir configurer les outils suivant :
- Faire la mise à jour d'Android Studio si nécessaire à la version Dolphin | 2021.3.1 Patch 1
- Télécharger postman pour tester les requêtes d'API : ajouter au header la clé "app-id" et en valeur votre app-id. Tester les différents end-points notamment récupérer une liste de posts, un post par id et un user par id.
Le domaine est le coeur de l'application qui contient la logique et les règles métier. Il est donc important que le domaine soit indépendant des autres modules et d'autres bibliothèques liées à l'UI, à Android, ... Mais aussi que toutes les classes (sauf les modèles) et les méthodes publiques soient testées.
Dans cette partie il faut modifier le module :domain
:
- Créer les modèles qui vont représenter un post détaillé (écran 2) et un utilisateur (écran 3). Ne pas hésiter à créer plusieurs
data class
ou à modifier les existantes si cela semble judicieux - Créer les interface des
Repositories
pour récupérer les données - Créer les
UseCases
qui vont permettre de récupérer les données. Ajouter les règles suivantes ou faire attention à :- Bien réfléchir à la gestion des dates / des durées : comment les représenter dans le domaine ?
- Suivant l'âge de l'utilisateur mettre une image ou une couleur de background différente
- Avoir une icône différente suivant le genre de la personne
- Faire les tests unitaires des
UseCases
La couche de données va permettre de récupérer et persister les données de l'application aux travers de Repositories
et des Data Sources
qui peuvent être locales avec un BDD ou distantes avec une API.
Dans cette partie il faut modifier la couche :api
:
- Ajouter les
DTO
et lesservices
qui permettront de récupérer les infos des posts et des utilisateurs en pensant à l'injection de dépendance Dans:data
: - Créer les Mapper entre DTO et les modèles de
:domain
et ajouter les TU - Implémenter les
Repositories
du:domain
sans oublier de les injecter et de les tester
Le rôle de l'UI est d'afficher les données de l'application à l'écran et de servir de point principal d'interaction utilisateur. Le pattern le plus utilisé est MVVM (Model - View - ViewModel) avec :
- Un modèle spécifique à la couche présentation (ici VO pour View Object)
- Une Vue soit :
- classique : avec un fichier XML statique et un Fragment dynamique
- compose : un seul fichier kotlin contenant une vue composable
- Un ViewModel qui va récupérer la données via des UseCases et qui va l'envoyer à la vue.
Deux prérequis avant de commencer le dév :
- Générer un module Android
:post
. Modifier le build.gradle pour ajouter les dépendances nécessaires et faire dépendre le module:app
du module créé - Faire de même pour
:user
- Dans ces deux modules créer un fragment vide.
Pour cette partie il est nécessaire de lire cette doc et cette doc pour comprendre la navigation entre une vue basée sur du XML et une vue en Jetpack Compose
.
- Dans les modules
:home
,:post
et:user
générer des graph de navigation qui vont contenir les fragments et qui vont gérer un deeplink à créer. - Dans le module
:app
générer un nouveau fichier de resource qui correspond au graph de navigation général. Modifier le layoutactivity_main
pour lier le nouveau navGraph et changer le name enNavHostFragment
.
Faire l'affichage d'un post en suivant l'architecture MVVM. Pour l'UI vous êtes libre. Si vous n'avez pas d'idée, vous pouvez vous inspirer du screenshot.
- Gérer le theming avec jetpack compose. L'idéal est de rationaliser les couleurs avec celles du thème classique cf ce tuto et utiliser la méthode
colorResource()
- Créer les VO pertinents et les mapper du modèle de domain vers modèle de présentation. Faire les TU des mappers
- Créer le ViewModel. Modifier le
UserFragment
pour que dans leonCreateView
il affiche unComposeView
. - Créer la vue compose avec trois méthodes composables, par exemple :
@Composable fun UserProfile()
"dynamique" : qui prend en paramètre le viewmodel et différentes lambda et appelle la méthode statique ci-après@Composable fun UserProfile()
"statique" : qui contient tout l'affichage@Preview(showSystemUi = true) @Composable fun UserProfilePreview()
: qui va appeler la méthode statique ci-avant et qui va permettre de visualiser une preview de la vue similairement à une vue XML
Ne pas hésiter à factoriser la vue compose en plusieurs fichiers pour plus de clareté.