1. Avant de commencer
Introduction
Dans de précédents ateliers de programmation, vous avez appris à extraire des données d'un service Web à l'aide d'un schéma de dépôt et à analyser la réponse dans un objet Kotlin. Dans cet atelier, vous allez vous appuyer sur ces connaissances pour charger et afficher des photos à partir d'une adresse URL. Vous verrez également à nouveau comment créer une LazyVerticalGrid
et l'utiliser pour afficher une grille d'images sur la page de présentation.
Conditions préalables
- Savoir récupérer des fichiers JSON à partir d'un service Web REST et analyser ces données dans des objets Kotlin à l'aide des bibliothèques Retrofit et Gson
- Avoir des connaissances sur le service Web REST
- Avoir de bonnes connaissances sur les composants d'architecture Android, comme la couche de données et le dépôt
- Avoir des connaissances sur l'injection de dépendances
- Avoir des connaissances sur
ViewModel
etViewModelProvider.Factory
- Avoir des connaissances sur l'implémentation de coroutines pour votre application
- Avoir des connaissances sur le schéma de dépôt
Points abordés
- Comment utiliser la bibliothèque Coil pour charger et afficher une image à partir d'une adresse URL
- Comment utiliser une
LazyVerticalGrid
pour afficher une grille d'images - Comment gérer les erreurs qui peuvent survenir lorsque les images se téléchargent et s'affichent
Objectifs de l'atelier
- Modifier l'application Mars Photos pour obtenir l'URL de l'image à partir des données de Mars, puis utiliser Coil pour charger et afficher cette image
- Ajouter une animation de chargement et une icône d'erreur à l'application
- Ajouter un état et une gestion des erreurs à l'application
Ce dont vous avez besoin
- Un ordinateur doté d'un navigateur Web récent (par exemple, la dernière version de Chrome)
- Le code de démarrage de l'application Mars Photos avec les services Web REST
2. Présentation de l'application
Dans cet atelier de programmation, vous allez utiliser l'application Mars Photos d'un atelier précédent. Cette application se connecte à un service Web pour récupérer les objets Kotlin et afficher leur nombre à l'aide de Gson. Ces objets Kotlin contiennent les URL des photos réelles de la surface de Mars prises par les rovers de la NASA.
La version de l'application que vous créez dans cet atelier de programmation affiche les photos de Mars dans une grille d'images. Les images font partie des données que l'application récupère à partir du service Web. Cette application utilise la bibliothèque Coil pour charger et afficher les images, ainsi que LazyVerticalGrid
pour les mettre en page sous la forme d'une grille. Elle affiche aussi un message d'erreur pratique en cas d'erreur réseau.
Télécharger le code de démarrage
Pour commencer, téléchargez le code de démarrage :
Vous pouvez également cloner le dépôt GitHub du code :
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-mars-photos.git $ cd basic-android-kotlin-compose-training-mars-photos $ git checkout coil-starter
Vous pouvez parcourir le code dans le dépôt GitHub Mars Photos
.
3. Afficher une image téléchargée
Même si afficher une photo à partir d'une URL peut sembler simple, plusieurs opérations sont nécessaires pour que cela fonctionne correctement. Vous devez télécharger l'image, la stocker dans la mémoire interne (en cache) et décoder son format compressé pour récupérer une image compatible avec Android. Vous pouvez la mettre en cache dans la mémoire, sur un support de stockage, voire dans les deux. Toutes ces opérations doivent être réalisées dans des threads en arrière-plan de faible priorité afin que l'UI reste réactive. Pour optimiser les performances du réseau et du processeur, vous pouvez également extraire et décoder plusieurs images à la fois.
Heureusement, vous pouvez utiliser Coil, une bibliothèque développée par la communauté, pour télécharger, mettre en mémoire tampon, décoder et mettre en cache vos images. Si vous décidez de vous passer de Coil, vous aurez beaucoup plus de travail.
Coil a besoin de deux choses :
- L'URL de l'image que vous voulez charger et afficher
- Un composable
AsyncImage
pour afficher réellement cette image
Dans cette tâche, vous allez apprendre à utiliser Coil pour afficher une seule image à partir du service Web Mars. Vous afficherez l'image de la photo de Mars figurant en premier dans la liste renvoyée par le service Web. Vous trouverez ci-dessous des captures d'écran avant et après :
Ajouter la dépendance Coil
- Ouvrez l'application Mars Photos de l'atelier de programmation Ajouter un dépôt et injecter manuellement des dépendances.
- Exécutez-la pour vérifier qu'elle affiche bien le nombre de photos de Mars récupérées.
- Ouvrez build.gradle.kts (Module :app).
- Dans la section
dependencies
(dépendances), ajoutez la ligne suivante pour la bibliothèque Coil :
// Coil
implementation("io.coil-kt:coil-compose:2.4.0")
Sur la page de documentation de la bibliothèque Coil, vérifiez quelle est la dernière version et faites la mise à jour.
- Cliquez sur Sync now (Synchroniser) pour recréer le projet avec la nouvelle dépendance.
Afficher l'URL de l'image
Au cours de cette étape, vous allez récupérer et afficher l'URL de la première photo de Mars.
- Dans
ui/screens/MarsViewModel.kt
, recherchez dans le bloctry
de la méthodegetMarsPhotos()
la ligne qui définit les données extraites du service Web surlistResult
.
// No need to copy, code is already present
try {
val listResult = marsPhotosRepository.getMarsPhotos()
//...
}
- Modifiez cette ligne en remplaçant
listResult
parresult
et en affectant la première photo de Mars récupérée à la nouvelle variableresult
. Affectez l'objet de la première photo à l'index0
.
try {
val result = marsPhotosRepository.getMarsPhotos()[0]
//...
}
- Sur la ligne suivante, remplacez le paramètre transmis à l'appel de fonction
MarsUiState.Success()
par la chaîne figurant dans le code ci-dessous. Utilisez les données de la nouvelle propriété au lieu delistResult
. Affichez l'URL de la première image issue duresult
de la photo.
try {
...
MarsUiState.Success("First Mars image URL: ${result.imgSrc}")
}
Le bloc try
complet se présente maintenant comme suit :
marsUiState = try {
val result = marsPhotosRepository.getMarsPhotos()[0]
MarsUiState.Success(
" First Mars image URL : ${result.imgSrc}"
)
}
- Exécutez l'application. Le composable
Text
affiche désormais l'URL de la première photo de Mars. La prochaine section explique comment faire en sorte que l'application affiche l'image de cette URL.
Ajouter un composable AsyncImage
Au cours de cette étape, vous allez ajouter une fonction modulable AsyncImage
pour charger et afficher une seule photo de Mars. AsyncImage
est un composable qui exécute une requête d'image de manière asynchrone et qui affiche le résultat.
// Example code, no need to copy over
AsyncImage(
model = "https://android.com/sample_image.jpg",
contentDescription = null
)
L'argument model
peut être soit la valeur ImageRequest.data
, soit l'ImageRequest
proprement dite. Dans l'exemple de code précédent, vous allez attribuer la valeur ImageRequest.data
(c'est-à-dire l'URL de l'image, qui est "https://android.com/sample_image.jpg"
). L'exemple de code ci-dessous montre comment attribuer la valeur ImageRequest
proprement dite au model
.
// Example code, no need to copy over
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data("https://example.com/image.jpg")
.crossfade(true)
.build(),
placeholder = painterResource(R.drawable.placeholder),
contentDescription = stringResource(R.string.description),
contentScale = ContentScale.Crop,
modifier = Modifier.clip(CircleShape)
)
AsyncImage
prend en charge les mêmes arguments que le composable Image standard. Il permet également de définir des peintures placeholder
/error
/fallback
et des rappels onLoading
/onSuccess
/onError
. L'exemple de code précédent charge l'image avec un recadrage dans un cercle et un fondu enchaîné, et définit un espace réservé.
contentDescription
définit le texte utilisé par les services d'accessibilité pour décrire ce que cette image représente.
Ajoutez un composable AsyncImage
à votre code pour afficher la première photo de Mars récupérée.
- Dans
ui/screens/HomeScreen.kt
, ajoutez une fonction modulable intituléeMarsPhotoCard()
, qui accepteMarsPhoto
etModifier
.
@Composable
fun MarsPhotoCard(photo: MarsPhoto, modifier: Modifier = Modifier) {
}
- Dans la fonction modulable
MarsPhotoCard()
, ajoutez la fonctionAsyncImage()
comme suit :
import coil.compose.AsyncImage
import coil.request.ImageRequest
import androidx.compose.ui.platform.LocalContext
@Composable
fun MarsPhotoCard(photo: MarsPhoto, modifier: Modifier = Modifier) {
AsyncImage(
model = ImageRequest.Builder(context = LocalContext.current)
.data(photo.imgSrc)
.build(),
contentDescription = stringResource(R.string.mars_photo),
modifier = Modifier.fillMaxWidth()
)
}
Dans le code précédent, vous allez créer une ImageRequest
avec l'URL de l'image (photo.imgSrc
) et la transmettre à l'argument model
. contentDescription
permet de définir le texte des lecteurs d'accessibilité.
- Ajoutez
crossfade(true)
àImageRequest
pour activer une animation en fondu enchaîné lorsque la requête aboutit.
@Composable
fun MarsPhotoCard(photo: MarsPhoto, modifier: Modifier = Modifier) {
AsyncImage(
model = ImageRequest.Builder(context = LocalContext.current)
.data(photo.imgSrc)
.crossfade(true)
.build(),
contentDescription = stringResource(R.string.mars_photo),
modifier = Modifier.fillMaxWidth()
)
}
- Modifiez le composable
HomeScreen
pour qu'il affiche le composableMarsPhotoCard
au lieu du composableResultScreen
lorsque la requête aboutit. Vous allez corriger l'erreur de non-correspondance de type à la prochaine étape.
@Composable
fun HomeScreen(
marsUiState: MarsUiState,
modifier: Modifier = Modifier
) {
when (marsUiState) {
is MarsUiState.Loading -> LoadingScreen(modifier = modifier.fillMaxSize())
is MarsUiState.Success -> MarsPhotoCard(photo = marsUiState.photos, modifier = modifier.fillMaxSize())
else -> ErrorScreen(modifier = modifier.fillMaxSize())
}
}
- Dans le fichier
MarsViewModel.kt
, modifiez l'interfaceMarsUiState
pour qu'elle accepte un objetMarsPhoto
au lieu d'un objetString
.
sealed interface MarsUiState {
data class Success(val photos: MarsPhoto) : MarsUiState
//...
}
- Modifiez la fonction
getMarsPhotos()
pour qu'elle transmette l'objet de la première photo de Mars àMarsUiState.Success()
. Supprimez la variableresult
.
marsUiState = try {
MarsUiState.Success(marsPhotosRepository.getMarsPhotos()[0])
}
- Exécutez l'application et vérifiez qu'elle affiche bien une seule image de Mars.
- La photo de Mars n'occupe pas tout l'écran. Pour qu'elle occupe l'espace disponible, dans
HomeScreen.kt
sousAsyncImage
, définissezcontentScale
surContentScale.Crop
.
import androidx.compose.ui.layout.ContentScale
@Composable
fun MarsPhotoCard(photo: MarsPhoto, modifier: Modifier = Modifier) {
AsyncImage(
model = ImageRequest.Builder(context = LocalContext.current)
.data(photo.imgSrc)
.crossfade(true)
.build(),
contentDescription = stringResource(R.string.mars_photo),
contentScale = ContentScale.Crop,
modifier = modifier,
)
}
- Exécutez l'application, et vérifiez que l'image occupe tout l'écran horizontalement et verticalement.
Ajouter des images de chargement et d'erreur
Vous pouvez améliorer l'expérience utilisateur dans votre application en affichant un espace réservé pour une image lorsqu'elle se charge. Vous pouvez également afficher une image d'erreur si le chargement échoue (par exemple, à cause d'un fichier image manquant ou corrompu). Dans cette section, vous allez ajouter à la fois des images d'erreur et d'espace réservé à l'aide de AsyncImage
.
- Ouvrez
res/drawable/ic_broken_image.xml
, puis cliquez sur l'onglet Design (Conception) ou Split (Diviser) à droite. Pour l'image d'erreur, utilisez l'icône d'image défectueuse disponible dans la bibliothèque d'icônes intégrée. Ce drawable vectoriel utilise l'attributandroid:tint
pour colorer l'icône en gris.
- Ouvrez
res/drawable/loading_img.xml
. Ce drawable est une animation qui fait pivoter une image drawable,loading_img.xml
, autour de son point central. (L'animation ne s'affiche pas dans l'aperçu.)
- Revenez au fichier
HomeScreen.kt
. Dans le composableMarsPhotoCard
, modifiez l'appel àAsyncImage()
pour ajouter les attributserror
etplaceholder
, comme indiqué dans le code ci-dessous :
import androidx.compose.ui.res.painterResource
@Composable
fun MarsPhotoCard(photo: MarsPhoto, modifier: Modifier = Modifier) {
AsyncImage(
// ...
error = painterResource(R.drawable.ic_broken_image),
placeholder = painterResource(R.drawable.loading_img),
// ...
)
}
Ce code définit l'image de chargement de l'espace réservé à utiliser lors du chargement (le drawable loading_img
). Il définit également l'image à utiliser en cas d'échec du chargement (le drawable ic_broken_image
).
Le composable MarsPhotoCard
complet se présente maintenant comme suit :
@Composable
fun MarsPhotoCard(photo: MarsPhoto, modifier: Modifier = Modifier) {
AsyncImage(
model = ImageRequest.Builder(context = LocalContext.current)
.data(photo.imgSrc)
.crossfade(true)
.build(),
error = painterResource(R.drawable.ic_broken_image),
placeholder = painterResource(R.drawable.loading_img),
contentDescription = stringResource(R.string.mars_photo),
contentScale = ContentScale.Crop
)
}
- Exécutez l'application. Selon la vitesse de votre connexion réseau, vous pouvez voir brièvement l'image de chargement pendant que Coil télécharge et affiche l'image de propriété. Toutefois, pour le moment, l'icône représentant une image défectueuse ne s'affichera pas même si vous désactivez votre réseau. Vous allez résoudre ce problème dans la dernière tâche de cet atelier de programmation.
4. Afficher une grille d'images avec LazyVerticalGrid
Votre application charge désormais une photo de Mars depuis Internet (le premier élément de la liste MarsPhoto
). Vous avez utilisé l'URL de l'image issue des données de cette photo de Mars pour insérer une AsyncImage
. Toutefois, l'objectif est que votre application affiche une grille d'images. Au cours de cette tâche, vous allez utiliser une LazyVerticalGrid
avec un gestionnaire de mise en page adapté pour afficher une grille d'images.
Grilles différées
Les composables LazyVerticalGrid et LazyHorizontalGrid permettent d'afficher des éléments dans une grille. Une grille verticale différée affiche ses éléments dans un conteneur à faire défiler verticalement, s'étendant sur plusieurs colonnes, tandis qu'une grille horizontale différée a le même comportement sur l'axe horizontal.
Du point de vue de la conception, la mise en page sous la forme de grille est idéale pour afficher des photos de Mars représentées par des icônes ou des images.
Les paramètres columns
dans LazyVerticalGrid
et rows
dans LazyHorizontalGrid
contrôlent la manière dont les cellules sont formées dans des colonnes ou des lignes. L'exemple de code ci-dessous affiche des éléments dans une grille, en utilisant GridCells.Adaptive
pour définir chaque colonne sur une largeur d'au moins 128.dp
:
// Sample code - No need to copy over
@Composable
fun PhotoGrid(photos: List<Photo>) {
LazyVerticalGrid(
columns = GridCells.Adaptive(minSize = 150.dp)
) {
items(photos) { photo ->
PhotoItem(photo)
}
}
}
LazyVerticalGrid
vous permet de spécifier une largeur pour les éléments. La grille s'adapte ensuite au plus grand nombre de colonnes possible. Une fois le nombre de colonnes calculé, la grille répartit équitablement les largeurs restantes entre les colonnes. Cette méthode de dimensionnement adaptative est particulièrement utile pour afficher des ensembles d'éléments sur différentes tailles d'écran.
Dans cet atelier de programmation, pour afficher des photos de Mars, vous allez utiliser le composable LazyVerticalGrid
avec GridCells.Adaptive
et une largeur de 150.dp
pour chaque colonne.
Clés d'élément
Lorsque l'utilisateur fait défiler la grille (une LazyRow
dans un LazyColumn
), la position de l'élément de liste change. Toutefois, en raison d'un changement d'orientation, voire de l'ajout ou de la suppression d'éléments, l'utilisateur peut perdre la position de défilement sur la ligne. Les clés associées aux éléments vous aident à conserver la position de défilement en fonction de la clé.
En fournissant des clés, vous aidez Compose à gérer les réorganisations correctement. Par exemple, si votre élément contient un état mémorisé, les clés permettent à Compose de déplacer cet état avec l'élément lorsque sa position change.
Ajouter LazyVerticalGrid
Ajoutez un composable pour afficher une liste de photos de Mars dans une grille verticale.
- Dans le fichier
HomeScreen.kt
, créez une fonction modulable intituléePhotosGridScreen()
, qui utilise une liste deMarsPhoto
et unmodifier
comme arguments.
@Composable
fun PhotosGridScreen(
photos: List<MarsPhoto>,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues(0.dp),
) {
}
- Dans le composable
PhotosGridScreen
, ajoutez uneLazyVerticalGrid
avec les paramètres suivants.
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.ui.unit.dp
@Composable
fun PhotosGridScreen(
photos: List<MarsPhoto>,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues(0.dp),
) {
LazyVerticalGrid(
columns = GridCells.Adaptive(150.dp),
modifier = modifier.padding(horizontal = 4.dp),
contentPadding = contentPadding,
) {
}
}
- Pour ajouter une liste d'éléments, dans le lambda
LazyVerticalGrid
, appelez la fonctionitems()
qui transmet la liste deMarsPhoto
et la clé d'élémentphoto.id
.
import androidx.compose.foundation.lazy.grid.items
@Composable
fun PhotosGridScreen(
photos: List<MarsPhoto>,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues(0.dp),
) {
LazyVerticalGrid(
// ...
) {
items(items = photos, key = { photo -> photo.id }) {
}
}
}
- Pour ajouter le contenu affiché par un seul élément de liste, définissez l'expression lambda
items
. AppelezMarsPhotoCard
en transmettant laphoto
.
items(items = photos, key = { photo -> photo.id }) {
photo -> MarsPhotoCard(photo)
}
- Modifiez le composable
HomeScreen
pour afficher le composablePhotosGridScreen
au lieu du composableMarsPhotoCard
lorsque la requête aboutit.
when (marsUiState) {
// ...
is MarsUiState.Success -> PhotosGridScreen(marsUiState.photos, modifier)
// ...
}
- Dans le fichier
MarsViewModel.kt
, modifiez l'interfaceMarsUiState
pour accepter une liste d'objetsMarsPhoto
au lieu d'un seul objetMarsPhoto
. Le composablePhotosGridScreen
accepte une liste d'objetsMarsPhoto
.
sealed interface MarsUiState {
data class Success(val photos: List<MarsPhoto>) : MarsUiState
//...
}
- Dans le fichier
MarsViewModel.kt
, modifiez la fonctiongetMarsPhotos()
pour transmettre une liste d'objets de photo de Mars àMarsUiState.Success()
.
marsUiState = try {
MarsUiState.Success(marsPhotosRepository.getMarsPhotos())
}
- Exécutez l'application.
Notez qu'il n'y a pas de marge intérieure autour de chaque photo et que le format diffère selon les photos. Vous pouvez ajouter un composable Card
pour résoudre ces problèmes.
Ajouter un composable Card
- Dans le fichier
HomeScreen.kt
, puis dans le composableMarsPhotoCard
, ajoutez une fonctionCard
avec une élévation de8.dp
autour deAsyncImage
. Attribuez l'argumentmodifier
au composableCard
.
import androidx.compose.material.Card
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.padding
@Composable
fun MarsPhotoCard(photo: MarsPhoto, modifier: Modifier = Modifier) {
Card(
modifier = modifier,
elevation = CardDefaults.cardElevation(defaultElevation = 8.dp)
) {
AsyncImage(
model = ImageRequest.Builder(context = LocalContext.current)
.data(photo.imgSrc)
.crossfade(true)
.build(),
error = painterResource(R.drawable.ic_broken_image),
placeholder = painterResource(R.drawable.loading_img),
contentDescription = stringResource(R.string.mars_photo),
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxWidth()
)
}
}
- Pour corriger le format, dans
PhotosGridScreen()
, redéfinissez le modificateur pourMarsPhotoCard()
.
@Composable
fun PhotosGridScreen(photos: List<MarsPhoto>, modifier: Modifier = Modifier) {
LazyVerticalGrid(
//...
) {
items(items = photos, key = { photo -> photo.id }) { photo ->
MarsPhotoCard(
photo,
modifier = modifier
.padding(4.dp)
.fillMaxWidth()
.aspectRatio(1.5f)
)
}
}
}
- Modifiez l'aperçu de l'écran de résultats pour prévisualiser
PhotosGridScreen()
. Simulez les données avec des URL d'images vides.
@Preview(showBackground = true) @Composable fun PhotosGridScreenPreview() { MarsPhotosTheme { val mockData = List(10) { MarsPhoto("$it", "") } PhotosGridScreen(mockData) } }
Étant donné que les données fictives contiennent des URL vides, des images de chargement sont affichées dans l'aperçu de la grille de photos.
- Exécutez l'application.
- Pendant l'exécution de l'application, activez le mode Avion.
- Faites défiler les images dans l'émulateur. À la place des images qui n'ont pas encore été chargées, des icônes d'images défectueuses s'affichent. Il s'agit de l'image drawable que vous avez transmise à la bibliothèque d'images Coil et qui s'affiche si une erreur réseau survient ou si une image ne peut pas être extraite.
Bien joué ! Vous avez simulé une erreur de connexion réseau en activant le mode Avion dans votre émulateur ou sur votre appareil.
5. Ajouter un bouton "Réessayer"
Dans cette section, vous ajouterez un bouton d'action "Réessayer" afin de récupérer les photos lorsque l'utilisateur clique sur celui-ci.
- Ajoutez un bouton à l'écran d'erreur. Dans le fichier
HomeScreen.kt
, modifiez le composableErrorScreen()
pour inclure un paramètre lambdaretryAction
et un bouton.
@Composable
fun ErrorScreen(retryAction: () -> Unit, modifier: Modifier = Modifier) {
Column(
// ...
) {
Image(
// ...
)
Text(//...)
Button(onClick = retryAction) {
Text(stringResource(R.string.retry))
}
}
}
Vérifier l'aperçu
- Modifiez le composable
HomeScreen()
pour transmettre le lambda de nouvelle tentative.
@Composable
fun HomeScreen(
marsUiState: MarsUiState, retryAction: () -> Unit, modifier: Modifier = Modifier
) {
when (marsUiState) {
//...
is MarsUiState.Error -> ErrorScreen(retryAction, modifier = modifier.fillMaxSize())
}
}
- Dans le fichier
ui/theme/MarsPhotosApp.kt
, modifiez l'appel de fonctionHomeScreen()
pour définir le paramètre lambdaretryAction
surmarsViewModel::getMarsPhotos
. Les photos de Mars seront ainsi récupérées sur le serveur.
HomeScreen(
marsUiState = marsViewModel.marsUiState,
retryAction = marsViewModel::getMarsPhotos
)
6. Modifier le test ViewModel
MarsUiState
et MarsViewModel
acceptent désormais une liste de photos au lieu d'une seule photo. Dans son état actuel, MarsViewModelTest
s'attend à ce que la classe de données MarsUiState.Success
contienne une propriété de chaîne. Par conséquent, le test n'est pas compilé. Vous devez modifier le test marsViewModel_getMarsPhotos_verifyMarsUiStateSuccess()
pour indiquer que MarsViewModel.marsUiState
est égal à l'état Success
contenant la liste de photos.
- Ouvrez le fichier
rules/MarsViewModelTest.kt
. - Dans le test
marsViewModel_getMarsPhotos_verifyMarsUiStateSuccess()
, modifiez l'appel de fonctionassertEquals()
pour comparer un étatSuccess
(en transmettant la liste de photos fictives au paramètre photos) àmarsViewModel.marsUiState
.
@Test
fun marsViewModel_getMarsPhotos_verifyMarsUiStateSuccess() =
runTest {
val marsViewModel = MarsViewModel(
marsPhotosRepository = FakeNetworkMarsPhotosRepository()
)
assertEquals(
MarsUiState.Success(FakeDataSource.photosList),
marsViewModel.marsUiState
)
}
Le test est à présent compilé, exécuté et conclu.
7. Télécharger le code de solution
Pour télécharger le code de l'atelier de programmation terminé, utilisez la commande Git suivante :
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-mars-photos.git
Vous pouvez également télécharger le dépôt sous forme de fichier ZIP, le décompresser et l'ouvrir dans Android Studio.
Si vous le souhaitez, vous pouvez consulter le code de solution de cet atelier de programmation sur GitHub.
8. Conclusion
Bravo ! Vous avez terminé cet atelier de programmation, et l'application Mars Photos est prête à l'emploi. Il est temps d'en profiter pour montrer de vraies photos de Mars à vos proches.
N'oubliez pas de partager le fruit de vos efforts sur les réseaux sociaux avec le hashtag #AndroidBasics.
9. En savoir plus
Documentation pour les développeurs Android :
- Listes et grilles | Jetpack Compose | Développeurs Android
- Grilles différées | Jetpack Compose | Développeurs Android
- Présentation de ViewModel
Autre :