443 votes

Quel est le principal objectif des méthodes setTag() getTag() de View ?

Quel est l'objectif principal de méthodes telles que setTag() et getTag() de View des objets de ce type ?

Ai-je raison de penser que je peux associer un nombre quelconque d'objets à une seule vue ?

655voto

Matthew Willis Points 26453

Disons que vous générez un tas de vues qui sont similaires. Vous pourriez définir un OnClickListener pour chaque vue individuellement :

button1.setOnClickListener(new OnClickListener ... );
button2.setOnClickListener(new OnClickListener ... );
 ...

Ensuite, vous devez créer un onClick pour chaque vue, même si elles font les mêmes choses, par exemple :

public void onClick(View v) {
    doAction(1); // 1 for button1, 2 for button2, etc.
}

Cela s'explique par le fait que onClick n'a qu'un seul paramètre, un View et il doit obtenir d'autres informations à partir de variables d'instance ou de variables locales finales dans les scopes englobants. Ce que nous voulons vraiment, c'est obtenir des informations des vues elles-mêmes .

Entrez getTag / setTag :

button1.setTag(1);
button2.setTag(2);

Nous pouvons maintenant utiliser le même OnClickListener pour chaque bouton :

listener = new OnClickListener() {
    @Override
    public void onClick(View v) {
        doAction(v.getTag());
    }
};

C'est essentiellement un moyen pour les vues d'avoir souvenirs .

9 votes

@Matthew Willis mais nous pouvons aussi le faire en utilisant view.getId(). n'est-ce pas ?

55 votes

@AndroidKiller vous pourriez, mais avec setTag() vous pouvez mettre n'importe quel objet que vous voulez, même des classes personnalisées - ainsi vous pouvez les utiliser pour persister une référence aux données que la vue affiche.

0 votes

Que dois-je faire si je veux seulement changer la couleur de fond du bouton sur lequel on a cliqué ? Je récupère la position par getTag().

137voto

Andrei Buneyeu Points 2812

Je voudrais ajouter quelques mots.

Bien que l'utilisation de get/setTag(Object) semble être très utile dans le cas particulier d'un pattern ViewHolder, je recommanderais de réfléchir à deux fois avant de l'utiliser dans d'autres cas. Il existe presque toujours une autre solution mieux conçue.

La raison principale est que ce genre de code devient rapidement insupportable.

  • Il n'est pas évident pour les autres développeurs de savoir ce que vous avez conçu pour stocker comme balise dans la vue. Les méthodes setTag/getTag ne sont pas du tout descriptifs.

  • Il stocke simplement un Object qui doit être lancé lorsque vous voulez getTag . Vous pouvez obtenir des plantages inattendus plus tard lorsque vous décidez de changer le type d'objet stocké dans la balise.

  • Voici une histoire vraie : Nous avions un projet assez important avec beaucoup d'adaptateurs, d'opérations asynchrones avec des vues, etc. Un développeur a décidé de set/getTag dans sa partie de code, mais un autre avait déjà défini la balise de cette vue. Au final, quelqu'un ne pouvait pas trouver sa propre balise et était très confus. Il nous a fallu plusieurs heures pour trouver le bug.

setTag(int key, Object tag) est bien meilleur, car vous pouvez générer des clés uniques pour chaque balise (en utilisant ressources id ), mais il existe une restriction importante pour Android < 4.0. Extrait de la documentation de Lint :

Avant Android 4.0, l'implémentation de View.setTag(int, Object) stockait les objets dans une carte statique, où les valeurs étaient fortement référencées. Cela signifie que si l'objet contient des références pointant vers le contexte, le contexte (qui pointe vers à peu près tout le reste) fuira. Si vous passez une vue, la vue fournit une référence au contexte qui l'a créée. De même, les view contiennent généralement une vue, et les curseurs sont parfois également associés à des vues.

2 votes

Merci, très utile ! ... Savez-vous si ce qui se trouve dans la balise est restauré entre les recréations d'activité ?

28voto

user3445599 Points 230

Nous pouvons utiliser setTag() et getTag() pour définir et obtenir des objets personnalisés en fonction de nos besoins. Le site setTag() prend un argument de type Object et getTag() renvoie un Object .

Par exemple,

Person p = new Person();
p.setName("Ramkailash");
p.setId(2000001);
button1.setTag(p);

23voto

Oren Points 101

Pour les développeurs web, cela semble être l'équivalent de data-

16voto

shubniggurath Points 98

C'est très utile pour la personnalisation ArrayAdapter en utilisant. Il s'agit d'une sorte d'optimisation. Il y a setTag utilisé comme référence à l'objet qui se réfère à certaines parties de la mise en page (qui affiche dans ListView ) au lieu de findViewById .

static class ViewHolder {
    TextView tvPost;
    TextView tvDate;
    ImageView thumb;
}

public View getView(int position, View convertView, ViewGroup parent) {

    if (convertView == null) {
        LayoutInflater inflater = myContext.getLayoutInflater();
        convertView = inflater.inflate(R.layout.postitem, null);

        ViewHolder vh = new ViewHolder();
        vh.tvPost = (TextView)convertView.findViewById(R.id.postTitleLabel);
        vh.tvDate = (TextView)convertView.findViewById(R.id.postDateLabel);
        vh.thumb = (ImageView)convertView.findViewById(R.id.postThumb);
        convertView.setTag(vh);
    }
            ....................
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X