méthodes getViewTypeCount et getItemViewType de ArrayAdapter

159

Quelqu'un peut-il en termes clairs m'expliquer l'utilisation getViewTypeCount()et les getItemViewType()méthodes de ArrayAdapter?

Eugène
la source

Réponses:

308

Celles-ci gèrent le cas où vous souhaitez différents types de vue pour différentes lignes. Par exemple, dans une application de contacts, vous pouvez souhaiter que les lignes paires aient des images sur le côté gauche et les lignes impaires sur la droite. Dans ce cas, vous utiliseriez:

@Override
public int getViewTypeCount() {
    return 2;
}

@Override
public int getItemViewType(int position) {
    return position % 2;
}

Le framework utilise votre type de vue pour décider des vues àconvertViewgetView utiliser dans votre méthode . En d'autres termes, dans l'exemple ci-dessus, vos lignes paires recevront uniquement des vues recyclées avec des images sur le côté gauche à réutiliser, et les lignes impaires n'en recevront que celles avec des images sur la droite.

Si chaque ligne de votre liste a la même disposition, vous n'avez pas à vous soucier des types de vues. En fait, BaseAdapter.java fournit un comportement par défaut pour tous les adaptateurs:

public int getItemViewType(int position) {
    return 0;
}

public int getViewTypeCount() {
    return 1;
}

Cela vous fournit en effet le même type de vue pour chaque ligne.

Modifier - pour décrire le flux général:

  1. Vous liez des données à votre à l' AdapterViewaide d'un adaptateur.
  2. Le AdapterViewtente d'afficher les éléments visibles par l'utilisateur.
  3. Le framework appelle getItemViewTyperow n, la ligne qu'il est sur le point d'afficher.
  4. Le framework vérifie son pool de vues recyclées pour les vues du ntype de ligne. Il n'en trouve pas car aucune vue n'a encore été recyclée.
  5. getViewest appelé pour la ligne n.
  6. Vous appelez getItemViewTypeune ligne npour déterminer le type de vue à utiliser.
  7. Vous utilisez une instruction if / switch pour gonfler un fichier xml différent en fonction du type de vue requis.
  8. Vous remplissez la vue d'informations.
  9. Vous retournez la vue, quittez getViewet la vue de votre ligne est affichée à l'utilisateur.

Désormais, lorsqu'une vue est recyclée en faisant défiler l'écran, elle entre dans un pool de vues recyclées qui est géré par le framework. Celles-ci sont essentiellement organisées par type de vue afin qu'une vue du type correct vous soit donnée en convertViewparamètre dans votre getViewméthode:

  1. Le framework appelle à nouveau getItemViewTypela ligne qu'il souhaite afficher.
  2. Cette fois, il y a une vue dans la piscine recyclée du type approprié.
  3. La vue recyclée vous est transmise en tant que convertViewparamètre de votre getViewméthode.
  4. Vous remplissez la vue recyclée avec de nouvelles informations et vous la renvoyez.
Matthew Willis
la source
1
@Matthew, merci pour votre réponse. Pouvez-vous décrire le flux comment ces méthodes sont appelées. De plus, je ne comprends pas comment cela est réellement associé à mes données dans res / layout.
Eugene
Il n'y a pas de contrat explicite pour le moment où ces méthodes sont appelées. res / layout est l'endroit pour les objets de vue . Ceci est un adaptateur . Vous devez vérifier le type d'élément dans votre méthode getView et gonfler la vue appropriée de res / layout en conséquence.
Matthew Willis
1
Vous le renvoyez vous-même dans getItemViewType.
Matthew Willis
Vous effectuez l'association manuellement dans getView: if (type == 0) {/ * gonfler R.layout.row_icon_on_left /} else {/ gonfler R.layout.row_icon_on_right * /}
Matthew Willis
75
Il faut se méfier! getItemViewType () doit renvoyer un entier entre 0 et getViewTypeCount () - 1.
PacificSky
12

Si nous avons besoin d'afficher un type de vue différent dans la vue de liste, il est bon à utiliser getViewTypeCount()et getItemViewType()dans l'adaptateur au lieu de basculer une vue View.GONEet View.VISIBLEpeut être une tâche très coûteuse à l'intérieur getView()qui affectera le défilement de la liste.

Veuillez vérifier celui-ci pour l'utilisation de getViewTypeCount()et getItemViewType()dans Adapter.

Lien: l'utilisation-de-getviewtypecount

kyogs
la source
Renvoyer IGNORE_ITEM_VIEW_TYPE dans getItemViewType () passera toujours 'view' comme null dans getView (position int, View view, ViewGroup viewGroup) forçant à initialiser tous les composants de l'interface utilisateur. N'est-ce pas un mauvais indicateur de performance dans lequel, en cas de modèle de support, nous pouvons réutiliser les vues d'interface utilisateur existantes et nous pouvons simplement basculer la vue sur View.GONE ou View.VISIBLE en fonction de la position.
Namrata Bagerwal
11

Regardez Outttt !!!!
J'ai dû faire face à un problème d'implémentation d'un ListViewhier et ce sont deux types de vues pour les lignes qui se sont mélangées juste après que je les fasse défiler. Même si la réponse la plus votée dans ce fil donne une bonne explication générale, elle n'a pas mis en évidence l'information la plus importante pour arrêter le bogue de l'interface utilisateur ci-dessus que j'ai mentionné.

Voici mon explication: les
deux getViewTypeCount()et getItemViewType()sont utilisés par BaseAdapterla getViewméthode de pour savoir quel type de vue doit être récupérée, recyclée et retournée. (comme expliqué dans la première réponse du fil de discussion). Mais si vous n'implémentez pas ces deux méthodes de manière intuitive selon le document d'API Android, vous risquez de vous retrouver dans le problème dont j'ai parlé.

Ligne directrice résumée pour l'implémentation:
Pour implémenter plusieurs types de lignes de Viewsfor ListView, nous devons essentiellement implémenter, getItemViewType()et des getViewTypeCount()méthodes. Et la getItemViewType()documentation nous donne une note comme suit:

Remarque: les nombres entiers doivent être compris entre 0les getViewTypeCount() - 1. IGNORE_ITEM_VIEW_TYPEpeut également être retourné.

Donc, dans votre, getItemViewType()vous devez renvoyer des valeurs pour le type de vue, en commençant par 0, jusqu'au dernier type comme (nombre de types - 1). Par exemple, disons que vous n'avez que trois types de vues? Ainsi, selon l'objet de données de la vue, vous ne pouvez renvoyer que 0 ou 1 ou 2 à partir de la getItemViewType()méthode, comme un index de tableau de base zéro. Et comme vous avez trois types de vues utilisées, votre getViewTypeCount()méthode doit renvoyer 3.

Dans tous les cas, si vous renvoyez d'autres valeurs entières telles que 1, 2, 3 ou 111, 222, 333 pour cette méthode, vous risquez certainement de rencontrer le bogue d'interface utilisateur ci-dessus que vous venez de placer en n'obéissant pas au document d'API Android.

Si vous ne comprenez pas ou ne pouvez toujours pas résoudre et avez besoin de plus d'informations, veuillez lire ma réponse détaillée dans ce fil de questions StackOverflow .

Lisez le document du développeur Android pour plus d'informations, vous pourriez trouver l'indice directement.

J'espère que cette réponse pourrait être utile à quelqu'un là-bas pour gagner beaucoup d'heures !!!

À votre santé!!!

Randika Vishman
la source
1
Merci d'avoir mentionné IGNORE_ITEM_VIEW_TYPEque j'avais un bug sur l'un de mes ListView. J'ai utilisé un ArrayAdapter pour insérer une vue composée de 1 image et 2 vues de texte. Je n'avais qu'un seul type de vue. J'ai essayé soit de ne pas remplacer la méthode getItemViewType, soit de la remplacer en renvoyant la position ou un entier codé en dur. Dans tous les cas, je rencontrais des doublons dans ma liste, avec un comportement étrange lors du défilement (changements de doublons). Le retour IGNORE_ITEM_VIEW_TYPEde la méthode a résolu le problème. Merci.
Alex
@Alex heureux que cela vous ait été utile! :-)
Randika Vishman