web-dev-qa-db-fra.com

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

Quel est le but principal de méthodes telles que setTag() et getTag() of View objets de type?

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

403
Eugene

Supposons que vous générez un ensemble de points de vue similaires. Vous pouvez définir un OnClickListener pour chaque vue individuellement:

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

Ensuite, vous devez créer une méthode unique onClick pour chaque vue, même si elles effectuent des tâches similaires, comme:

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

En effet, 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 des étendues englobantes. Ce que nous voulons vraiment, c'est obtenir des informations 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 fondamentalement un moyen d'avoir des vues mémoires.

613
Matthew Willis

J'aimerais ajouter quelques mots.

Bien que l'utilisation de get/setTag(Object) semble être très utile dans le cas particulier du modèle ViewHolder, je vous recommande de réfléchir à deux fois avant de l'utiliser dans les autres cas. Presque toujours, il existe une autre bonne solution de conception.

La raison principale est que le code devient rapidement insoutenable.

  • Ce que vous avez conçu pour stocker en tant que balise n’est pas évident pour les autres développeurs. Les méthodes setTag/getTag ne sont pas du tout descriptives.

  • Il stocke juste un Object, de sorte qu'il nécessite un transtypage lorsque vous voulez getTag. Vous pouvez avoir un crash inattendu plus tard lorsque vous décidez de changer le type d'objet stocké dans la balise.

  • C'est l'histoire de la vraie vie. Nous avons eu un assez gros projet avec beaucoup d'adaptateurs, des opérations asynchrones avec vues, etc. Un développeur a décidé de set/getTag dans sa partie de code, mais un autre avait déjà défini balise pour cette vue. À la fin, quelqu'un n'a pas pu trouver sa propre étiquette et était très confus. Cela nous a coûté plusieurs heures pour trouver le bogue.

setTag(int key, Object tag) semble beaucoup mieux, car vous pouvez générer des clés uniques pour chaque balise (en utilisant id resources ), mais il existe une restriction importante pour Android <4.0. De la charpie docs:

Avant Android 4.0, la mise en œuvre de View.setTag (int, Object) stockait les objets dans une carte statique, dans laquelle les valeurs étaient fortement référencées. Cela signifie que si l'objet contient des références renvoyant au contexte, le contexte (qui pointe à peu près tout le reste) va fuir. Si vous transmettez une vue, celle-ci 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 des curseurs sont parfois associés à des vues.

117
Andrei Buneyeu

Nous pouvons utiliser setTag() et getTag() pour définir et obtenir des objets personnalisés selon nos besoins. La méthode 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);
25
Ramkailash

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

19
Oren

Ceci est très utile pour personnaliser ArrayAdapter using. C'est une sorte d'optimisation. Il setTag a été utilisé comme référence à un objet faisant référence à certaines parties de la mise en page (celui affichant 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);
    }
            ....................
}
14
shubniggurath

Contrairement aux ID, les balises ne sont pas utilisées pour identifier les vues. Les tags sont essentiellement des informations supplémentaires pouvant ê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 de les placer dans une structure séparée.

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

12
Saad Bilal

La définition de balises est très utile lorsque vous avez un ListView et que vous souhaitez recycler/réutiliser les vues. Ainsi, ListView est en train de devenir très similaire à la plus récente 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;
}
10
user5053330