Android Recyclerview vs ListView avec Viewholder

148

Je suis récemment tombé sur l'androïde RecyclerViewqui a été publié avec Android 5.0 et il semble que ce ne RecyclerViewsoit qu'un traditionnel encapsulé ListViewavec le modèle ViewHolder incorporé, ce qui favorise la réutilisation de la vue, plutôt que de la créer à chaque fois.

Quels sont les autres avantages de l'utilisation RecyclerView? Si les deux ont le même effet en termes de performances, pourquoi préférerait-on RecyclerView?

Éditer

J'ai constaté que les gens ont posé des questions similaires et que les réponses ne sont pas concluantes, les ajoutant ici pour la tenue de registres.

Recyclerview vs Listview

Devrions-nous utiliser RecyclerView pour remplacer ListView?

Pourquoi RecyclerView n'a-t-il pas onItemClickListener ()? et En quoi RecyclerView est-il différent de Listview?

Mushtaq Jameel
la source
4
Parce que le RecyclerViewest beaucoup plus rapide et polyvalent avec une bien meilleure API. Des choses comme l'animation de l'ajout ou de la suppression d'éléments sont déjà implémentées dans le RecyclerViewsans que vous ayez à faire quoi que ce soit. Il n'y a aucun doute là-dessus, jetez votre ListViewpoubelle à la poubelle, RecyclerViewc'est là pour voler la vedette.
Xaver Kapeller
4
Vous pouvez associer un gestionnaire de disposition à un RecyclerView, afin qu'ils ne soient pas limités aux listes à défilement vertical. C'est une fonctionnalité supplémentaire assez puissante.
Alan
@Alan - Qu'entendez-vous par "non limité à des listes déroulantes verticalement"? Êtes-vous en train de dire que la vue de recyclage peut également agir comme un «espace réservé» pour les vues en grille et les vues de liste?
Mushtaq Jameel
@XaverKapeller - Ce serait formidable si vous pouviez énumérer les différences entre les deux et répondre à la question plutôt que sur un commentaire, afin que cela puisse m'aider, moi et les autres à l'avenir, qui pourraient se demander la même chose?
Mushtaq Jameel
@Alan - Pourriez-vous fournir un peu de détails sur ce que vous vouliez dire et répondre à la question plutôt qu'à un commentaire. Merci de prendre le temps
Mushtaq Jameel

Réponses:

289

Avec l'avènement d'Android Lollipop, le RecyclerView a fait son chemin officiellement. Le RecyclerView est beaucoup plus puissant, flexible et constitue une amélioration majeure par rapport à ListView . Je vais essayer de vous en donner un aperçu détaillé.

1) Modèle ViewHolder

Dans un ListView, il était recommandé d'utiliser le modèle ViewHolder mais ce n'était jamais une contrainte. Dans le cas de RecyclerView, cela est obligatoire à l'aide de la classe RecyclerView.ViewHolder . C'est l'une des principales différences entre le ListView et le RecyclerView.

Cela rend les choses un peu plus complexes dans RecyclerView mais beaucoup de problèmes auxquels nous avons été confrontés dans ListView sont résolus efficacement.

2) LayoutManager

Il s'agit d'une autre amélioration massive apportée au RecyclerView. Dans un ListView, le seul type d'affichage disponible est le ListView vertical. Il n'existe aucun moyen officiel d'implémenter même un ListView horizontal.

Maintenant en utilisant un RecyclerView, nous pouvons avoir un

i) LinearLayoutManager - qui prend en charge les listes verticales et horizontales,

ii) StaggeredLayoutManager - qui prend en charge Pinterest comme des listes échelonnées,

iii) GridLayoutManager - qui prend en charge l'affichage des grilles comme on le voit dans les applications Galerie.

Et la meilleure chose est que nous pouvons faire tout cela dynamiquement comme nous le voulons.

3) Animateur d'objets

Les ListViews manquent pour prendre en charge de bonnes animations, mais le RecyclerView lui apporte une toute nouvelle dimension. Utilisation de RecyclerView.ItemAnimator classe , l'animation des vues devient tellement simple et intuitive.

4) Décoration d'article

Dans le cas de ListViews, la décoration dynamique d'éléments comme l'ajout de bordures ou de séparateurs n'a jamais été facile. Mais dans le cas de RecyclerView, la classe RecyclerView.ItemDecorator donne un contrôle énorme aux développeurs mais rend les choses un peu plus longues et complexes.

5) OnItemTouchListener

L'interception des clics sur un élément ListView était simple, grâce à son interface AdapterView.OnItemClickListener . Mais le RecyclerView donne beaucoup plus de puissance et de contrôle à ses développeurs grâce au RecyclerView.OnItemTouchListener ( n'est plus pris en charge, veuillez vous référer à AndroidX ) mais cela complique un peu les choses pour le développeur.

En termes simples, le RecyclerView est beaucoup plus personnalisable que le ListView et donne beaucoup de contrôle et de puissance à ses développeurs.

Aritra Roy
la source
34
Bonne réponse. Quelques énormes avantages supplémentaires: RecyclerView prépare la vue juste avant et derrière les entrées visibles, ce qui est idéal si vous récupérez des images bitmap en arrière-plan. Les performances sont considérablement plus rapides, en particulier si vous utilisez RecyclerView.setHasFixedSize. L'ancien ListView est basé sur le principe qu'il n'y a aucun moyen de précalculer ou de mettre en cache la taille des entrées dans la liste, ce qui entraîne des complications insensées lors du défilement et de la mise en page. Il faut du temps pour s'y habituer, mais une fois que vous l'aurez fait, vous ne reviendrez jamais en arrière.
Robin Davies
@RobinDavies Excellent point. Merci d'avoir informé. Mais cela n'aura aucun sens si les tailles des articles sont différentes.
Aritra Roy
@AritraRoy Recyclerview prend en charge sur sucette uniquement ou api 14+ (Android 4+) également? .... comme je l'ai lu "après sucette: dans la plupart des endroits
Animesh Mangla
2
Hé, Aritra, en comparant à ListView, si ListView utilise également ViewHolder Pattern, lequel agit le plus efficacement? RecylerView le mieux, lors de l'utilisation de fps ou d'un autre critère similaire other thx ~
RxRead
@RxRead: Voir le commentaire de Robin, il différencie RecyclerView Vs ListView avec le modèle de détenteur de vue en raison de la performance.
Parag Kadam
10

L'autre avantage de l'utilisation RecycleViewest l'animation, cela peut être fait en deux lignes de code

RecyclerView.ItemAnimator itemAnimator = new DefaultItemAnimator();
        recyclerView.setItemAnimator(itemAnimator);

Mais le widget est toujours brut, par exemple vous ne pouvez pas créer d'en- tête et de pied de page .

Etun
la source
5
Et vous ne pourrez jamais créer un en-tête et un pied de page dans ce sens. Ce ne sont que d'autres types de vues dans votre adaptateur. La vue Liste englobe votre adaptateur HeaderViewListAdapteret ajoute la prise en charge de l'en-tête en arrière-plan. Avec RecyclerViewvous êtes celui qui contrôle.
Eugen Pechanec
RecyclerView utilise un DefaultItemAnimator par défaut. Alors pourquoi avez-vous utilisé ce code?
Athira Reddy
9

Ok, si peu de fouille et j'ai trouvé ces gemmes de l' article de Bill Philips surRecycleView

RecyclerView peut faire plus que ListView, mais la classe RecyclerView elle-même a moins de responsabilités que ListView. Hors de la boîte, RecyclerView ne:

  • Positionner les éléments sur l'écran
  • Animer les vues
  • Gérez tous les événements tactiles en dehors du défilement

Tous ces éléments ont été intégrés à ListView, mais RecyclerView utilise à la place des classes de collaborateurs pour effectuer ces tâches.

Les ViewHolders que vous créez sont également plus robustes. Ils sous-classent RecyclerView.ViewHolder - , qui a un tas d' RecyclerView utilisations de méthodes . ViewHolderssavoir à quelle position ils sont actuellement liés, ainsi que les identifiants d'élément (si vous en avez). Dans le processus, ViewHolder a été fait chevalier. Auparavant, c'était le travail de ListView de conserver la vue entière de l'élément, et de ViewHolderne s'en tenir qu'à de petits morceaux.

Maintenant, ViewHolder conserve tout cela dans le ViewHolder.itemView champ, qui est affecté dans le constructeur de ViewHolder pour vous.

Mushtaq Jameel
la source
4

Plus de l' article de Bill Phillip (allez le lire!) Mais j'ai pensé qu'il était important de souligner ce qui suit.

Dans ListView, il y avait une certaine ambiguïté sur la façon de gérer les événements de clic: les vues individuelles devraient-elles gérer ces événements ou le ListView devrait-il les gérer via OnItemClickListener? Dans RecyclerView, cependant, le ViewHolder est dans une position claire pour agir comme un objet contrôleur au niveau de la ligne qui gère ces types de détails.

Nous avons vu plus haut que LayoutManager gérait les vues de positionnement et ItemAnimator les animait. ViewHolder est le dernier élément: il est responsable de la gestion de tous les événements qui se produisent sur un élément spécifique que RecyclerView affiche.

Jaison Brooks
la source
2

J'ai utilisé un ListViewchargeur d'images avec Glide, ayant une croissance de la mémoire. Ensuite, j'ai remplacé le ListViewpar un RecyclerView. Ce n'est pas seulement plus difficile dans le codage, mais conduit également à une utilisation de la mémoire plus qu'unListView . Du moins, dans mon projet.

Dans une autre activité, j'ai utilisé une liste complexe avec EditText's. Dans certains d'entre eux, une méthode de saisie peut varier, un TextWatcherpeut également être appliqué. Si j'utilisais a ViewHolder, comment pourrais-je remplacer a TextWatcherpendant le défilement? Donc, j'ai utilisé un ListViewsans a ViewHolder, et ça marche.

CoolMind
la source
J'ai utilisé un ListView sans ViewHolder, et cela fonctionne. idée terrible ... comment pourrais-je remplacer un TextWatcher pendant le défilement? il n'est pas nécessaire de le remplacer ... juste TextWacher doit mettre les données dans un conteneur différent après la réutilisation ... et cela peut être fait très facilement
Selvin
@Selvin, merci pour votre avis. Maintenant, je ne peux pas modifier ce projet. Il y avait plusieurs TextWatchers sur un écran. Vous avez probablement raison, mais je ne peux pas le vérifier.
CoolMind
1

Réutilise les cellules en faisant défiler vers le haut / vers le bas - cela est possible avec l'implémentation de View Holder dans l'adaptateur listView, mais c'était une chose facultative, alors que dans RecycleView, c'est le moyen par défaut d'écrire l'adaptateur.

Découple la liste de son conteneur - afin que vous puissiez placer facilement des éléments de liste au moment de l'exécution dans les différents conteneurs (linearLayout, gridLayout) avec le paramètre LayoutManager.

Exemple:

mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
//or
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 2));
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));
  • Anime les actions de liste courantes.

  • Les animations sont découplées et déléguées à ItemAnimator.

Il y a plus sur RecyclerView, mais je pense que ces points sont les principaux.

LayoutManager

i) LinearLayoutManager - qui prend en charge les listes verticales et horizontales,

ii) StaggeredLayoutManager - qui prend en charge Pinterest comme des listes échelonnées,

iii) GridLayoutManager - qui prend en charge l'affichage des grilles comme on le voit dans les applications Galerie.

Et la meilleure chose est que nous pouvons faire tout cela dynamiquement comme nous le voulons.

Keshav Gera
la source
1

1. Afficher les détenteurs

Dans ListView, la définition des détenteurs de vue était une approche suggérée pour conserver les références des vues. Mais ce n'était pas une contrainte. Bien qu'en ne le faisant pas, ListView a utilisé des données obsolètes. Un autre inconvénient majeur de ne pas utiliser de détenteurs de vue pourrait conduire à une opération lourde de recherche de vues par ID à chaque fois. Ce qui a abouti à des ListViews laggy.

Ce problème est résolu dans RecylerView par l'utilisation de la classe RecyclerView.ViewHolder. C'est l'une des principales différences entre RecyclerView et ListView. Lors de l'implémentation d'un RecyclerView, cette classe est utilisée pour définir un objet ViewHolder qui est utilisé par l'adaptateur pour lier ViewHolder à une position. Un autre point à noter ici, est que lors de l'implémentation de l'adaptateur pour RecyclerView, la fourniture d'un ViewHolder est obligatoire. Cela rend l'implémentation un peu complexe, mais résout les problèmes rencontrés dans ListView.

2. Gestionnaire de mise en page

Quand on parle de ListViews, un seul type de ListView est disponible à savoir le ListView vertical. Vous ne pouvez pas implémenter un ListView avec un défilement horizontal. Je sais qu'il existe des moyens d'implémenter un défilement horizontal, mais croyez-moi, il n'a pas été conçu pour fonctionner de cette façon.

Mais maintenant, lorsque nous examinons Android RecyclerView vs ListView, nous prenons également en charge les collections horizontales. En fait, il prend en charge plusieurs types de listes. Pour prendre en charge plusieurs types de listes, il utilise la classe RecyclerView.LayoutManager. C'est quelque chose de nouveau que ListView n'a pas. RecyclerView prend en charge trois types de gestionnaires de mise en page prédéfinis:

LinearLayoutManager - Il s'agit du gestionnaire de disposition le plus couramment utilisé dans le cas de RecyclerView. Grâce à cela, nous pouvons créer des listes de défilement horizontales et verticales. StaggeredGridLayoutManager - Grâce à ce gestionnaire de mise en page, nous pouvons créer des listes échelonnées. Tout comme l'écran Pinterest. GridLayoutManager - Ce gestionnaire de mise en page peut être utilisé pour afficher des grilles, comme n'importe quelle galerie d'images.

3. Animateur d'objets

Les animations dans une liste sont une toute nouvelle dimension, qui a des possibilités infinies. Dans un ListView, en tant que tel, il n'y a pas de dispositions spéciales à travers lesquelles on peut animer, ajouter ou supprimer des éléments. Au lieu de cela plus tard, ViewPropertyAnimator a été suggéré par Google's Chet Haase dans ce didacticiel vidéo pour les animations dans ListView.

D'autre part, en comparant Android RecyclerView et ListView, il dispose de la classe RecyclerView.ItemAnimator pour la gestion des animations. Grâce à cette classe, des animations personnalisées peuvent être définies pour les événements d'ajout, de suppression et de déplacement d'éléments. En outre, il fournit un DefaultItemAnimator, au cas où vous n'auriez pas besoin de personnalisations.

4. Adaptateur

Les adaptateurs ListView étaient simples à implémenter. Ils avaient une méthode principale getView où toute la magie se produisait. Où les vues étaient liées à une position. De plus, ils avaient une méthode intéressante registerDataSetObserver où l'on peut définir un observateur directement dans l'adaptateur. Cette fonctionnalité est également présente dans RecyclerView, mais la classe RecyclerView.AdapterDataObserver est utilisée pour cela. Mais le point en faveur de ListView est qu'il prend en charge trois implémentations par défaut d'adaptateurs:

ArrayAdapter CursorAdapter SimpleCursorAdapter Alors que l'adaptateur RecyclerView, possède toutes les fonctionnalités des adaptateurs ListView, à l'exception de la prise en charge intégrée des curseurs DB et des ArrayLists. Dans RecyclerView.Adapter à partir de maintenant, nous devons créer une implémentation personnalisée pour fournir des données à l'adaptateur. Tout comme le fait un BaseAdapter pour ListViews. Bien que si vous souhaitez en savoir plus sur l'implémentation de l'adaptateur RecyclerView, reportez-vous à l'exemple Android RecyclerView.

5. Notification des changements de données

Lorsque vous travaillez avec un ListView, si l'ensemble de données est modifié, vous devez appeler la méthode notifyDataSetChanged de l'adaptateur sous-jacent pour actualiser les données. Ou définissez la méthode setNotifyOnChange sur true si vous souhaitez appeler automatiquement la méthode notifyDataSetChanged. Mais dans les deux cas, le résultat est très lourd sur la liste. Fondamentalement, il actualise les vues de la liste.

Mais au contraire, dans un adaptateur RecyclerView, si un seul élément ou une plage d'éléments a changé, il existe des méthodes pour notifier le changement en conséquence. Ceux-ci sont respectivement notifyItemChanged et notifyItemRangeChanged et bien d'autres comme:

notifyItemInsterted notifyItemMoved notifyItemRangeInsterted notifyItemRangeRemoved Et bien sûr, il a la méthode originale pour actualiser toute la liste, c'est-à-dire notifyDataSetChanged qui notifie l'adapté que l'ensemble de données a changé.

6. Décoration d'article

Pour afficher des diviseurs personnalisés dans un ListView, on aurait pu facilement ajouter ces paramètres dans le XML ListView:

XHTML android: divider = "@ android: color / transparent" android: dividerHeight = "5dp" 1 2 android: divider = "@ android: color / transparent" android: dividerHeight = "5dp" La partie intéressante d'Android RecyclerView est que, à partir de maintenant, il n'affiche pas de séparateur entre les éléments par défaut. Bien que les gars de Google aient dû laisser cela de côté pour la personnalisation, intentionnellement. Mais cela augmente considérablement l'effort d'un développeur. Si vous souhaitez ajouter un séparateur entre les éléments, vous devrez peut-être effectuer une implémentation personnalisée à l'aide de la classe RecyclerView.ItemDecoration.

Ou vous pouvez appliquer un hack en utilisant ce fichier à partir d'exemples officiels: DividerItemDecoration.java

7. OnItemTouchListener

Les listviews avaient une implémentation simple pour la détection des clics, c'est-à-dire par l'utilisation de l'interface AdapterView.OnItemClickListener.

Mais d'autre part, l'interface RecyclerView.OnItemTouchListener est utilisée pour détecter les événements tactiles dans Android RecyclerView. Cela complique un peu l'implémentation, mais cela donne un plus grand contrôle au développeur pour intercepter les événements tactiles. La documentation officielle indique qu'il peut être utile pour les manipulations gestuelles car il intercepte un événement tactile avant qu'il ne soit livré à RecyclerView.

Raviraj
la source
1

RecyclerView a été créé en tant qu'amélioration de ListView, donc oui, vous pouvez créer une liste jointe avec le contrôle ListView, mais l'utilisation de RecyclerView est plus simple car elle:

  1. Réutilise les cellules en faisant défiler vers le haut / vers le bas : cela est possible avec l'implémentation de View Holder dans l'adaptateur ListView, mais c'était une chose facultative, alors que dans RecycleView, c'est la manière par défaut d'écrire l'adaptateur.

  2. Découple la liste de son conteneur : vous pouvez donc placer facilement des éléments de liste au moment de l'exécution dans les différents conteneurs (linearLayout, gridLayout) avec le paramètre LayoutManager.

mRecyclerView = (RecyclerView) findViewById (R.id.my_recycler_view); mRecyclerView.setLayoutManager (nouveau LinearLayoutManager (this)); mRecyclerView.setLayoutManager (nouveau GridLayoutManager (this, 2));

  1. Animation des actions de liste courantes : les animations sont découplées et déléguées à ItemAnimator. Il y a plus sur RecyclerView, mais je pense que ces points sont les principaux.

Donc, pour conclure, RecyclerView est un contrôle plus flexible pour la gestion des "données de liste" qui suit des modèles de délégation des préoccupations et ne laisse qu'une seule tâche - le recyclage des articles.

farzin borujerdi
la source
0

Si vous utilisez RecycleView, vous avez d'abord besoin de plus d'efforts pour la configuration. Vous devez donner plus de temps pour configurer un élément simple en un clic, une bordure, un événement tactile et d'autres choses simples. Mais le produit final sera parfait.

La décision vous appartient donc. Je suggère que si vous concevez une application simple comme le chargement du répertoire, où un simple clic sur l'élément suffit, vous pouvez implémenter la liste. Mais si vous concevez comme une page d'accueil de médias sociaux avec un défilement illimité. Plusieurs décorations différentes entre les éléments, beaucoup de contrôle de l'élément individuel que l'utilisation de la vue de recyclage.

Mahbubur Rahman Khan
la source