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

421

Quel est le but principal de telles méthodes setTag()et getTag()d' Viewobjets de type?

Ai-je raison de penser que je peux associer n'importe quel nombre d'objets à une seule vue?

Eugène
la source

Réponses:

636

Disons que vous générez un tas de vues similaires. Vous pouvez définir un OnClickListenerpour chaque vue individuellement:

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

Ensuite, vous devez créer une onClickméthode unique pour chaque vue, même si elles font les mêmes choses, comme:

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

En effet, il onClickn'a qu'un seul paramètre, a View, et il doit obtenir d'autres informations à partir des variables d'instance ou des variables locales finales dans les étendues englobantes. Ce que nous voulons vraiment, c'est obtenir des informations à partir des vues elles-mêmes .

Entrez getTag/ setTag:

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

Maintenant, nous pouvons 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 des souvenirs .

Matthew Willis
la source
8
@Matthew Willis, mais nous pouvons aussi le faire en utilisant view.getId (). n'est-ce pas ?
Android Killer
50
@AndroidKiller vous pourriez, mais avec setTag () vous pouvez mettre n'importe quel objet que vous voulez, même des classes personnalisées - vous pouvez donc les utiliser pour conserver une référence aux données que la vue affiche
Daniel
Que dois-je faire si je veux seulement changer la couleur d'arrière-plan du bouton sur lequel on clique ??? J'obtiens la position par getTag ().
Sagar Devanga
2
@Sagar: public void ui_click(View view){ if(20==((int)view.getTag())) view.setBackgroundColor(colorInt); }devrait faire l'affaire pour la partie couleur. 20 n'est qu'un espace réservé pour la position de validation de votre vue.
RiA
Je pense que c'est l'ancienne méthode. la nouvelle façon est d'utiliser des arguments génériques qui assurent la sécurité des types. mais c'est quand même bien.
M.kazem Akhgary
124

Je voudrais ajouter quelques mots.

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

La raison principale est qu'un code comme celui-ci devient assez rapidement insupportable.

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

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

  • Voici une histoire réelle: nous avions un assez gros projet avec beaucoup d'adaptateurs, des opérations asynchrones avec des vues, etc. Un développeur a décidé de le faire set/getTagdans sa partie du code, mais un autre a déjà défini la balise sur cette vue. En fin de compte, quelqu'un n'a pas pu trouver sa propre étiquette et était très confus. Il nous a fallu plusieurs heures pour trouver le bug.

setTag(int key, Object tag)semble beaucoup mieux, car vous pouvez générer des clés uniques pour chaque balise (en utilisant les ressources id ), mais il existe une restriction importante pour Android <4.0. De documents 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 à 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 détenteurs de vues contiennent généralement une vue et les curseurs sont parfois également associés à des vues.

Andrei Buneyeu
la source
2
Merci, très utile! ... Savez-vous par hasard si le contenu de la balise est restauré entre les activités récréatives?
gunar
25

Nous pouvons utiliser setTag()et getTag()pour définir et obtenir des objets personnalisés selon nos besoins. La setTag()méthode prend un argument de type Objectet getTag()retourne un Object.

Par exemple,

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

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

Oren
la source
14

Ceci est très utile pour une ArrayAdapterutilisation personnalisée . C'est une sorte d'optimisation. Il setTagutilisé comme référence à l'objet qui fait référence à certaines parties de la mise en page (celle qui s'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);
    }
            ....................
}
shubniggurath
la source
13

Contrairement aux ID, les balises ne sont pas utilisées pour identifier les vues. Les balises sont essentiellement des informations supplémentaires qui peuvent être associées à une vue. Ils sont le plus souvent utilisés pour faciliter le stockage des données relatives aux vues dans les vues elles-mêmes plutôt que pour les placer dans une structure distincte.

Référence: http://developer.android.com/reference/android/view/View.html

Saad Bilal
la source
11

La définition de TAG est vraiment utile lorsque vous disposez d'un ListView et que vous souhaitez recycler / réutiliser les vues. De cette façon, le ListView devient très similaire au nouveau RecyclerView.

@Override
public View getView(int position, View convertView, ViewGroup parent)
  {
ViewHolder holder = null;

if ( convertView == null )
{
    /* There is no view at this position, we create a new one. 
       In this case by inflating an xml layout */
    convertView = mInflater.inflate(R.layout.listview_item, null);  
    holder = new ViewHolder();
    holder.toggleOk = (ToggleButton) convertView.findViewById( R.id.togOk );
    convertView.setTag (holder);
}
else
{
    /* We recycle a View that already exists */
    holder = (ViewHolder) convertView.getTag ();
}

// Once we have a reference to the View we are returning, we set its values.

// Here is where you should set the ToggleButton value for this item!!!

holder.toggleOk.setChecked( mToggles.get( position ) );

return convertView;
}

la source