Principes de base d'Android en Kotlin 07.2 : DiffUtil et liaison de données avec RecyclerView

Cet atelier de programmation fait partie du cours Principes de base d'Android en Kotlin. Vous tirerez pleinement parti de ce cours en suivant les ateliers de programmation dans l'ordre. Tous les ateliers de programmation du cours sont listés sur la page de destination des ateliers de programmation Principes de base d'Android en Kotlin.

Introduction

Dans l'atelier de programmation précédent, vous avez mis à jour l'application TrackMySleepQuality pour afficher des données sur la qualité du sommeil dans un RecyclerView. Les techniques que vous avez apprises lorsque vous avez créé votre premier RecyclerView suffisent pour la plupart des RecyclerViews qui affichent des listes simples et pas trop longues. Toutefois, il existe un certain nombre de techniques qui rendent RecyclerView plus efficace pour les listes volumineuses et qui facilitent la gestion et l'extension de votre code pour les listes et les grilles complexes.

Dans cet atelier de programmation, vous allez vous appuyer sur l'application de suivi du sommeil de l'atelier de programmation précédent. Vous apprendrez une méthode plus efficace pour mettre à jour la liste des données de sommeil et à utiliser la liaison de données avec RecyclerView. (Si vous n'avez pas l'application de l'atelier de programmation précédent, vous pouvez télécharger le code de démarrage pour cet atelier de programmation.)

Ce que vous devez déjà savoir

  • Créer une interface utilisateur de base à l'aide d'une activité, de fragments et de vues.
  • Naviguer entre les fragments et utiliser safeArgs pour transmettre des données entre les fragments.
  • Affichez les modèles, les fabriques de modèles, les transformations et les LiveData, ainsi que leurs observateurs.
  • Création d'une base de données Room, d'un DAO et définition d'entités
  • Utiliser des coroutines pour les tâches de base de données et autres tâches de longue durée
  • Implémenter un RecyclerView de base avec une mise en page Adapter, ViewHolder et d'élément.

Points abordés

  • Comment utiliser DiffUtil pour mettre à jour efficacement une liste affichée par RecyclerView.
  • Utiliser la liaison de données avec RecyclerView
  • Utiliser des adaptateurs de liaison pour transformer des données.

Objectifs de l'atelier

  • Utilisez l'application TrackMySleepQuality de l'atelier de programmation précédent de cette série.
  • Mettez à jour SleepNightAdapter pour mettre à jour efficacement la liste à l'aide de DiffUtil.
  • Implémentez la liaison de données pour RecyclerView, en utilisant des adaptateurs de liaison pour transformer les données.

L'application de suivi du sommeil comporte deux écrans, représentés par des fragments, comme illustré dans la figure ci-dessous.

Le premier écran, affiché à gauche, comporte des boutons permettant de démarrer et d'arrêter le suivi. L'écran affiche certaines données de sommeil de l'utilisateur. Le bouton Effacer supprime définitivement toutes les données que l'application a collectées pour l'utilisateur. Le deuxième écran, à droite, permet de sélectionner une note de qualité du sommeil.

Cette application est conçue pour utiliser un contrôleur d'UI, ViewModel et LiveData, ainsi qu'une base de données Room pour conserver les données de sommeil.

Les données sur le sommeil sont affichées dans un RecyclerView. Dans cet atelier de programmation, vous allez créer la partie DiffUtil et la partie de liaison de données pour RecyclerView. À la fin de cet atelier de programmation, votre application aura exactement la même apparence, mais elle sera plus efficace, plus facile à mettre à l'échelle et plus facile à gérer.

Vous pouvez continuer à utiliser l'application SleepTracker de l'atelier de programmation précédent ou télécharger l'application RecyclerViewDiffUtilDataBinding-Starter depuis GitHub.

  1. Si nécessaire, téléchargez l'application RecyclerViewDiffUtilDataBinding-Starter depuis GitHub et ouvrez le projet dans Android Studio.
  2. Exécutez l'application.
  3. Ouvrez le fichier SleepNightAdapter.kt.
  4. Examinez le code pour vous familiariser avec la structure de l'application. Reportez-vous au diagramme ci-dessous pour récapituler l'utilisation de RecyclerView avec le modèle d'adaptateur pour afficher les données de sommeil à l'utilisateur.

  • À partir des entrées utilisateur, l'application crée une liste d'objets SleepNight. Chaque objet SleepNight représente une nuit de sommeil, sa durée et sa qualité.
  • SleepNightAdapter adapte la liste des objets SleepNight en un élément que RecyclerView peut utiliser et afficher.
  • L'adaptateur SleepNightAdapter produit des ViewHolders qui contiennent les vues, les données et les métadonnées permettant à la vue du recyclage d'afficher les données.
  • RecyclerView utilise SleepNightAdapter pour déterminer le nombre d'éléments à afficher (getItemCount()). RecyclerView utilise onCreateViewHolder() et onBindViewHolder() pour obtenir les supports de vue liés aux données à afficher.

La méthode notifyDataSetChanged() est inefficace

Pour indiquer à RecyclerView qu'un élément de la liste a été modifié et doit être mis à jour, le code actuel appelle notifyDataSetChanged() dans SleepNightAdapter, comme indiqué ci-dessous.

var data =  listOf<SleepNight>()
   set(value) {
       field = value
       notifyDataSetChanged()
   }

Toutefois, notifyDataSetChanged() indique à RecyclerView que la liste entière est potentiellement non valide. Par conséquent, RecyclerView lie et redessine chaque élément de la liste, y compris ceux qui ne sont pas visibles à l'écran. Cela représente beaucoup de travail inutile. Pour les listes volumineuses ou complexes, ce processus peut prendre suffisamment de temps pour que l'affichage clignote ou saccade lorsque l'utilisateur fait défiler la liste.

Pour résoudre ce problème, vous pouvez indiquer à RecyclerView exactement ce qui a changé. RecyclerView peut alors mettre à jour uniquement les vues qui ont changé à l'écran.

RecyclerView dispose d'une API riche pour mettre à jour un seul élément. Vous pouvez utiliser notifyItemChanged() pour indiquer à RecyclerView qu'un élément a été modifié. Vous pouvez utiliser des fonctions similaires pour les éléments ajoutés, supprimés ou déplacés. Vous pourriez tout faire manuellement, mais cette tâche serait loin d'être simple et pourrait impliquer pas mal de code.

Heureusement, il existe une meilleure solution.

DiffUtil est efficace et fait le gros du travail pour vous.

RecyclerView comporte une classe appelée DiffUtil, qui permet de calculer les différences entre deux listes. DiffUtil prend une ancienne liste et une nouvelle liste, et identifie les différences. Il trouve les éléments qui ont été ajoutés, supprimés ou modifiés. Il utilise ensuite un algorithme appelé Eugene W. Myers pour déterminer le nombre minimal de modifications à apporter à l'ancienne liste pour produire la nouvelle.

Une fois que DiffUtil a identifié les modifications, RecyclerView peut utiliser ces informations pour ne mettre à jour que les éléments qui ont été modifiés, ajoutés, supprimés ou déplacés. C'est beaucoup plus efficace que de refaire toute la liste.

Dans cette tâche, vous allez mettre à niveau SleepNightAdapter pour utiliser DiffUtil afin d'optimiser RecyclerView pour les modifications apportées aux données.

Étape 1 : Implémenter SleepNightDiffCallback

Pour utiliser la fonctionnalité de la classe DiffUtil, étendez DiffUtil.ItemCallback.

  1. Ouvrez SleepNightAdapter.kt.
  2. Sous la définition complète de la classe SleepNightAdapter, créez une classe de premier niveau appelée SleepNightDiffCallback qui étend DiffUtil.ItemCallback. Transmettez SleepNight en tant que paramètre générique.
class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>() {
}
  1. Placez le curseur sur le nom de la classe SleepNightDiffCallback.
  2. Appuyez sur Alt+Enter (Option+Enter sur Mac), puis sélectionnez Implement Members (Implémenter les membres).
  3. Dans la boîte de dialogue qui s'ouvre, cliquez sur OK en maintenant la touche Maj enfoncée pour sélectionner les méthodes areItemsTheSame() et areContentsTheSame().

    Des stubs sont alors générés dans SleepNightDiffCallback pour les deux méthodes, comme indiqué ci-dessous. DiffUtil utilise ces deux méthodes pour déterminer comment la liste et les éléments ont changé.
    override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
  1. Dans areItemsTheSame(), remplacez TODO par un code qui teste si les deux éléments SleepNight transmis, oldItem et newItem, sont identiques. Si les éléments ont le même nightId, ils sont identiques. Renvoie donc true. Sinon, renvoie false. DiffUtil utilise ce test pour déterminer si un élément a été ajouté, supprimé ou déplacé.
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
   return oldItem.nightId == newItem.nightId
}
  1. Dans areContentsTheSame(), vérifiez si oldItem et newItem contiennent les mêmes données, c'est-à-dire s'ils sont égaux. Cette vérification d'égalité portera sur tous les champs, car SleepNight est une classe de données. Les classes Data définissent automatiquement equals et quelques autres méthodes pour vous. S'il existe des différences entre oldItem et newItem, ce code indique à DiffUtil que l'élément a été mis à jour.
override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
   return oldItem == newItem
}

Il est courant d'utiliser un RecyclerView pour afficher une liste qui change. RecyclerView fournit une classe d'adaptateur, ListAdapter, qui vous aide à créer un adaptateur RecyclerView basé sur une liste.

ListAdapter assure le suivi de la liste pour vous et avertit l'adaptateur lorsque la liste est mise à jour.

Étape 1 : Modifiez votre adaptateur pour étendre ListAdapter

  1. Dans le fichier SleepNightAdapter.kt, modifiez la signature de la classe SleepNightAdapter pour étendre ListAdapter.
  2. Si vous y êtes invité, importez androidx.recyclerview.widget.ListAdapter.
  3. Ajoutez SleepNight comme premier argument à ListAdapter, avant SleepNightAdapter.ViewHolder.
  4. Ajoutez SleepNightDiffCallback() en tant que paramètre au constructeur. ListAdapter utilisera ces informations pour identifier ce qui a changé dans la liste. La signature de votre classe SleepNightAdapter terminée devrait se présenter comme suit.
class SleepNightAdapter : ListAdapter<SleepNight, SleepNightAdapter.ViewHolder>(SleepNightDiffCallback()) {
  1. Dans la classe SleepNightAdapter, supprimez le champ data, y compris le setter. Vous n'en avez plus besoin, car ListAdapter garde la trace de la liste pour vous.
  2. Supprimez le remplacement de getItemCount(), car ListAdapter implémente cette méthode pour vous.
  3. Pour éliminer l'erreur dans onBindViewHolder(), modifiez la variable item. Au lieu d'utiliser data pour obtenir un item, appelez la méthode getItem(position) fournie par ListAdapter.
val item = getItem(position)

Étape 2 : Utilisez submitList() pour maintenir la liste à jour

Votre code doit indiquer à l'élément ListAdapter quand une liste modifiée est disponible. ListAdapter fournit une méthode appelée submitList() pour indiquer à ListAdapter qu'une nouvelle version de la liste est disponible. Lorsque cette méthode est appelée, ListAdapter compare la nouvelle liste à l'ancienne et détecte les éléments qui ont été ajoutés, supprimés, déplacés ou modifiés. ListAdapter met ensuite à jour les éléments affichés par RecyclerView.

  1. Ouvrez SleepTrackerFragment.kt.
  2. Dans onCreateView(), dans l'observateur sur sleepTrackerViewModel, recherchez l'erreur où la variable data que vous avez supprimée est référencée.
  3. Remplacez adapter.data = it par un appel à adapter.submitList(it). Le code mis à jour est indiqué ci-dessous.

sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
   it?.let {
       adapter.submitList(it)
   }
})
  1. Exécutez votre application. Elle s'exécute plus rapidement, mais vous ne le remarquerez peut-être pas si votre liste est petite.

Dans cette tâche, vous allez utiliser la même technique que dans les ateliers de programmation précédents pour configurer la liaison de données et éliminer les appels à findViewById().

Étape 1 : Ajoutez la liaison de données au fichier de mise en page

  1. Ouvrez le fichier de mise en page list_item_sleep_night.xml dans l'onglet Texte.
  2. Placez le curseur sur la balise ConstraintLayout, puis appuyez sur Alt+Enter (Option+Enter sur un Mac). Le menu d'intention (le menu "Correction rapide") s'ouvre.
  3. Sélectionnez Convert to data binding layout (Convertir en mise en page de liaison de données). Cela encapsule la mise en page dans <layout> et ajoute une balise <data> à l'intérieur.
  4. Si nécessaire, faites défiler l'écran vers le haut et, dans la balise <data>, déclarez une variable nommée sleep.
  5. Définissez type sur le nom complet de SleepNight, com.example.android.trackmysleepquality.database.SleepNight. Votre balise <data> terminée devrait se présenter comme suit.
   <data>
        <variable
            name="sleep"
            type="com.example.android.trackmysleepquality.database.SleepNight"/>
    </data>
  1. Pour forcer la création de l'objet Binding, sélectionnez Build > Clean Project (Compiler > Nettoyer le projet), puis Build > Rebuild Project (Compiler > Recompiler le projet). (Si vous rencontrez toujours des problèmes, sélectionnez File > Invalidate Caches / Restart (Fichier > Invalider les caches/Redémarrer).) L'objet de liaison ListItemSleepNightBinding, ainsi que le code associé, sont ajoutés aux fichiers générés du projet.

Étape 2 : Développez la mise en page de l'élément à l'aide de la liaison de données

  1. Ouvrez SleepNightAdapter.kt.
  2. Dans la classe ViewHolder, recherchez la méthode from().
  3. Supprimez la déclaration de la variable view.

Code à supprimer :

val view = layoutInflater
       .inflate(R.layout.list_item_sleep_night, parent, false)
  1. À l'emplacement de la variable view, définissez une nouvelle variable appelée binding qui augmente l'objet de liaison ListItemSleepNightBinding, comme indiqué ci-dessous. Importez l'objet de liaison nécessaire.
val binding =
ListItemSleepNightBinding.inflate(layoutInflater, parent, false)
  1. À la fin de la fonction, au lieu de renvoyer view, renvoyez binding.
return ViewHolder(binding)
  1. Pour corriger l'erreur, placez votre curseur sur le mot binding. Appuyez sur Alt+Enter (Option+Enter sur Mac) pour ouvrir le menu d'intention.
  1. Sélectionnez Modifier le type de paramètre "itemView" du constructeur principal de la classe "ViewHolder" en "ListItemSleepNightBinding". Cela met à jour le type de paramètre de la classe ViewHolder.

  1. Faites défiler l'écran vers le haut jusqu'à la définition de la classe ViewHolder pour voir la modification de la signature. Une erreur s'affiche pour itemView, car vous avez remplacé itemView par binding dans la méthode from().

    Dans la définition de la classe ViewHolder, effectuez un clic droit sur l'une des occurrences de itemView, puis sélectionnez Refactor > Rename (Refactoriser > Renommer). Remplacez le nom par binding.
  2. Ajoutez le préfixe val au paramètre de constructeur binding pour en faire une propriété.
  3. Dans l'appel à la classe parente, RecyclerView.ViewHolder, remplacez le paramètre binding par binding.root. Vous devez transmettre un View, et binding.root est le ConstraintLayout racine dans la mise en page de votre élément.
  4. Votre déclaration de classe terminée devrait ressembler au code ci-dessous.
class ViewHolder private constructor(val binding: ListItemSleepNightBinding) : RecyclerView.ViewHolder(binding.root){

Une erreur s'affiche également pour les appels à findViewById(). Vous allez la corriger ensuite.

Étape 3 : Remplacer findViewById()

Vous pouvez désormais mettre à jour les propriétés sleepLength, quality et qualityImage pour utiliser l'objet binding au lieu de findViewById().

  1. Modifiez les initialisations de sleepLength, qualityString et qualityImage pour qu'elles utilisent les vues de l'objet binding, comme indiqué ci-dessous. Votre code ne devrait plus afficher d'erreurs.
val sleepLength: TextView = binding.sleepLength
val quality: TextView = binding.qualityString
val qualityImage: ImageView = binding.qualityImage

Avec l'objet de liaison en place, vous n'avez plus besoin de définir les propriétés sleepLength, quality et qualityImage. DataBinding mettra en cache les recherches, il n'est donc pas nécessaire de déclarer ces propriétés.

  1. Effectuez un clic droit sur les noms des propriétés sleepLength, quality et qualityImage. Sélectionnez Refactor > Inline (Refactoriser > Intégrer) ou appuyez sur Control+Command+N (Option+Command+N sur Mac).
  2. Exécutez votre application. (Vous devrez peut-être nettoyer et recompiler votre projet s'il comporte des erreurs.)

Dans cette tâche, vous allez mettre à niveau votre application pour qu'elle utilise la liaison de données avec des adaptateurs de liaison afin de définir les données dans vos vues.

Dans un atelier de programmation précédent, vous avez utilisé la classe Transformations pour prendre des LiveData et générer des chaînes mises en forme à afficher dans des vues de texte. Toutefois, si vous devez lier différents types ou des types complexes, vous pouvez fournir des adaptateurs de liaison pour aider la liaison de données à utiliser ces types. Les adaptateurs de liaison sont des adaptateurs qui prennent vos données et les transforment en un élément que la liaison de données peut utiliser pour lier une vue, comme du texte ou une image.

Vous allez implémenter trois adaptateurs de liaison, un pour l'image de qualité et un pour chaque champ de texte. En résumé, pour déclarer un adaptateur de liaison, vous devez définir une méthode qui reçoit un élément et une vue, et l'annoter avec @BindingAdapter. Dans le corps de la méthode, vous implémentez la transformation. En Kotlin, vous pouvez écrire un adaptateur de liaison en tant que fonction d'extension sur la classe de vue qui reçoit les données.

Étape 1 : Créez des adaptateurs de liaison

Notez que vous devrez importer un certain nombre de cours lors de cette étape, mais qu'ils ne seront pas mentionnés individuellement.

  1. Ouvrez SleepNightAdapater.kt.
  2. Dans la classe ViewHolder, recherchez la méthode bind() et rappelez-vous ce qu'elle fait. Vous allez prendre le code qui calcule les valeurs de binding.sleepLength, binding.quality et binding.qualityImage, et l'utiliser à l'intérieur de l'adaptateur. (Pour l'instant, laissez le code tel quel. Vous le déplacerez à une étape ultérieure.)
  3. Dans le package sleeptracker, créez et ouvrez un fichier appelé BindingUtils.kt.
  4. Déclarez une fonction d'extension sur TextView, appelée setSleepDurationFormatted, et transmettez un SleepNight. Cette fonction sera votre adaptateur pour calculer et mettre en forme la durée du sommeil.
fun TextView.setSleepDurationFormatted(item: SleepNight) {}
  1. Dans le corps de setSleepDurationFormatted, liez les données à la vue comme vous l'avez fait dans ViewHolder.bind(). Appelez convertDurationToFormatted(), puis définissez le text de TextView sur le texte mis en forme. (Comme il s'agit d'une fonction d'extension sur TextView, vous pouvez accéder directement à la propriété text.)
text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, context.resources)
  1. Pour informer la liaison de données de cet adaptateur de liaison, annotez la fonction avec @BindingAdapter.
  2. Cette fonction est l'adaptateur pour l'attribut sleepDurationFormatted. Transmettez donc sleepDurationFormatted en tant qu'argument à @BindingAdapter.
@BindingAdapter("sleepDurationFormatted")
  1. Le deuxième adaptateur définit la qualité du sommeil en fonction de la valeur d'un objet SleepNight. Créez une fonction d'extension appelée setSleepQualityString() sur TextView et transmettez un SleepNight.
  2. Dans le corps, liez les données à la vue comme vous l'avez fait dans ViewHolder.bind(). Appelez convertNumericQualityToString et définissez text.
  3. Annotez la fonction avec @BindingAdapter("sleepQualityString").
@BindingAdapter("sleepQualityString")
fun TextView.setSleepQualityString(item: SleepNight) {
   text = convertNumericQualityToString(item.sleepQuality, context.resources)
}
  1. Le troisième adaptateur de liaison définit l'image sur une vue d'image. Créez la fonction d'extension sur ImageView, appelez setSleepImage et utilisez le code de ViewHolder.bind(), comme indiqué ci-dessous.
@BindingAdapter("sleepImage")
fun ImageView.setSleepImage(item: SleepNight) {
   setImageResource(when (item.sleepQuality) {
       0 -> R.drawable.ic_sleep_0
       1 -> R.drawable.ic_sleep_1
       2 -> R.drawable.ic_sleep_2
       3 -> R.drawable.ic_sleep_3
       4 -> R.drawable.ic_sleep_4
       5 -> R.drawable.ic_sleep_5
       else -> R.drawable.ic_sleep_active
   })
}

Étape 2 : Mettez à jour SleepNightAdapter

  1. Ouvrez SleepNightAdapter.kt.
  2. Supprimez tout le contenu de la méthode bind(), car vous pouvez désormais utiliser la liaison de données et vos nouveaux adaptateurs pour effectuer ce travail à votre place.
fun bind(item: SleepNight) {
}
  1. Dans bind(), attribuez le sommeil à item, car vous devez informer l'objet de liaison de votre nouveau SleepNight.
binding.sleep = item
  1. Sous cette ligne, ajoutez binding.executePendingBindings(). Cet appel est une optimisation qui demande à la liaison de données d'exécuter immédiatement toutes les liaisons en attente. Il est toujours recommandé d'appeler executePendingBindings() lorsque vous utilisez des adaptateurs de liaison dans un RecyclerView, car cela peut accélérer légèrement le dimensionnement des vues.
 binding.executePendingBindings()

Étape 3 : Ajoutez des liaisons à la mise en page XML

  1. Ouvrez list_item_sleep_night.xml.
  2. Dans ImageView, ajoutez une propriété app portant le même nom que l'adaptateur de liaison qui définit l'image. Transmettez la variable sleep, comme indiqué ci-dessous.

    Cette propriété crée la connexion entre la vue et l'objet de liaison, via l'adaptateur. Chaque fois que sleepImage est référencé, l'adaptateur adapte les données de SleepNight.
app:sleepImage="@{sleep}"
  1. Procédez de la même façon pour les vues de texte sleep_length et quality_string. Chaque fois que sleepDurationFormatted ou sleepQualityString sont référencés, les adaptateurs adaptent les données de SleepNight.
app:sleepDurationFormatted="@{sleep}"
app:sleepQualityString="@{sleep}"
  1. Exécutez votre application. Elle fonctionne exactement comme avant. Les adaptateurs de liaison se chargent de la mise en forme et de la mise à jour des vues lorsque les données changent, ce qui simplifie ViewHolder et donne au code une structure bien meilleure qu'auparavant.

Vous avez affiché la même liste pour les derniers exercices. C'est voulu, pour vous montrer que l'interface Adapter vous permet d'architecturer votre code de nombreuses manières différentes. Plus votre code est complexe, plus il est important de bien l'architecturer. Dans les applications de production, ces modèles et d'autres sont utilisés avec RecyclerView. Tous les modèles fonctionnent et présentent chacun des avantages. Le choix dépend de ce que vous créez.

Félicitations ! Vous êtes bien parti pour maîtriser RecyclerView sur Android.

Projet Android Studio : RecyclerViewDiffUtilDataBinding.

DiffUtil :

  • RecyclerView comporte une classe appelée DiffUtil, qui permet de calculer les différences entre deux listes.
  • DiffUtil comporte une classe appelée ItemCallBack que vous étendez pour déterminer la différence entre deux listes.
  • Dans la classe ItemCallback, vous devez remplacer les méthodes areItemsTheSame() et areContentsTheSame().

ListAdapter :

  • Pour gérer des listes sans frais, vous pouvez utiliser la classe ListAdapter au lieu de RecyclerView.Adapter. Toutefois, si vous utilisez ListAdapter, vous devez écrire votre propre adaptateur pour les autres mises en page. C'est pourquoi cet atelier de programmation vous montre comment procéder.
  • Pour ouvrir le menu d'intention dans Android Studio, placez le curseur sur n'importe quel élément de code et appuyez sur Alt+Enter (Option+Enter sur Mac). Ce menu est particulièrement utile pour refactoriser le code et créer des stubs pour implémenter des méthodes. Le menu est contextuel. Vous devez donc placer le curseur exactement au bon endroit pour obtenir le menu approprié.

Liaison de données :

  • Utilisez la liaison de données dans la mise en page de l'élément pour lier les données aux vues.

Adaptateurs de liaison :

  • Vous avez déjà utilisé Transformations pour créer des chaînes à partir de données. Si vous devez lier des données de types différents ou complexes, fournissez des adaptateurs de liaison pour aider la liaison de données à les utiliser.
  • Pour déclarer un adaptateur de liaison, définissez une méthode qui prend un élément et une vue, puis annotez la méthode avec @BindingAdapter. En Kotlin, vous pouvez écrire l'adaptateur de liaison en tant que fonction d'extension sur View. Transmettez le nom de la propriété que l'adaptateur adapte. Exemple :
@BindingAdapter("sleepDurationFormatted")
  • Dans la mise en page XML, définissez une propriété app portant le même nom que l'adaptateur de liaison. Transmettez une variable avec les données. Exemple :
.app:sleepDurationFormatted="@{sleep}"

Cours Udacity :

Documentation pour les développeurs Android :

Autres ressources :

Cette section répertorie les devoirs possibles pour les élèves qui suivent cet atelier de programmation dans le cadre d'un cours animé par un enseignant. Il revient à l'enseignant d'effectuer les opérations suivantes :

  • Attribuer des devoirs si nécessaire
  • Indiquer aux élèves comment rendre leurs devoirs
  • Noter les devoirs

Les enseignants peuvent utiliser ces suggestions autant qu'ils le souhaitent, et ne doivent pas hésiter à attribuer d'autres devoirs aux élèves s'ils le jugent nécessaire.

Si vous suivez cet atelier de programmation par vous-même, n'hésitez pas à utiliser ces devoirs pour tester vos connaissances.

Répondre aux questions suivantes

Question 1

Parmi les éléments suivants, lesquels sont nécessaires pour utiliser DiffUtil ? Plusieurs réponses possibles.

▢ Étendez la classe ItemCallBack.

▢ Ignorer areItemsTheSame().

▢ Ignorer areContentsTheSame().

▢ Utiliser la liaison de données pour suivre les différences entre les éléments.

Question 2

Parmi les affirmations suivantes sur les adaptateurs de liaison, lesquelles sont vraies ?

▢ Un adaptateur de liaison est une fonction annotée avec @BindingAdapter.

▢ L'utilisation d'un adaptateur de liaison vous permet de séparer le formatage des données du conteneur de la vue.

▢ Vous devez utiliser un RecyclerViewAdapter si vous souhaitez utiliser des adaptateurs de liaison.

▢ Les adaptateurs de liaison constituent une excellente solution lorsque vous devez transformer des données complexes.

Question 3

Quand devriez-vous envisager d'utiliser Transformations au lieu d'un adaptateur de liaison ? Plusieurs réponses possibles.

▢ Vos données sont simples.

▢ Vous mettez en forme une chaîne.

▢ Votre liste est très longue.

▢ Votre ViewHolder ne contient qu'une seule vue.

Passez à la leçon suivante : 7.3 : GridLayout avec RecyclerView