¿Cuál es el propósito principal de los métodos de vista setTag () getTag ()?

421

¿Cuál es el propósito principal de métodos como setTag()y getTag()de Viewobjetos tipo?

¿Estoy en lo cierto al pensar que puedo asociar cualquier número de objetos con una sola Vista?

Eugene
fuente

Respuestas:

636

Digamos que genera un montón de vistas que son similares. Puede establecer un OnClickListenerpara cada vista individualmente:

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

Luego, debe crear un onClickmétodo único para cada vista, incluso si hacen cosas similares, como:

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

Esto se debe a que onClicksolo tiene un parámetro, a View, y tiene que obtener otra información de las variables de instancia o de las variables locales finales en los ámbitos adjuntos. Lo que realmente queremos es obtener información de las propias vistas .

Entrar getTag/ setTag:

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

Ahora podemos usar el mismo OnClickListener para cada botón:

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

Básicamente es una forma de que las vistas tengan recuerdos .

Matthew Willis
fuente
8
@Matthew Willis, pero también podemos hacerlo usando view.getId (). No lo es ?
Android Killer
50
@AndroidKiller podría, pero con setTag () puede poner cualquier objeto que desee, incluso clases personalizadas, para que pueda usarlos para persistir una referencia a los datos que muestra la vista
Daniel
¿Qué debo hacer si solo quiero cambiar el color de fondo del botón en el que se hace clic? Estoy obteniendo el puesto por getTag ().
Sagar Devanga
2
@Sagar: public void ui_click(View view){ if(20==((int)view.getTag())) view.setBackgroundColor(colorInt); }debería hacer el truco para la parte de color. 20 es solo un marcador de posición para la posición de validación de su Vista.
RiA
Creo que este es el viejo camino. La nueva forma es utilizar argumentos genéricos que proporcionen seguridad de tipo. pero esto es bueno, sin embargo.
M.kazem Akhgary
124

Me gustaría agregar algunas palabras.

Aunque el uso get/setTag(Object)parece ser muy útil en el caso particular de un patrón ViewHolder, recomendaría pensarlo dos veces antes de usarlo en otros casos. Casi siempre hay otra solución con un mejor diseño.

La razón principal es que un código como ese deja de ser compatible con bastante rapidez.

  • No es obvio para otros desarrolladores lo que diseñó para almacenar como etiqueta en la vista. Los métodos setTag/getTagno son descriptivos en absoluto.

  • Simplemente almacena un Object, que requiere ser lanzado cuando quieras getTag. Puede obtener bloqueos inesperados más adelante cuando decida cambiar el tipo de objeto almacenado en la etiqueta.

  • Aquí hay una historia de la vida real: tuvimos un proyecto bastante grande con muchos adaptadores, operaciones asincrónicas con vistas, etc. Un desarrollador decidió set/getTagen su parte del código, pero otro ya había establecido la etiqueta para esta vista. Al final, alguien no pudo encontrar su propia etiqueta y estaba muy confundido. Nos costó varias horas encontrar el error.

setTag(int key, Object tag)se ve mucho mejor, porque puede generar claves únicas para cada etiqueta (usando recursos de identificación ), pero hay una restricción significativa para Android <4.0. De documentos de pelusa:

Antes de Android 4.0, la implementación de View.setTag (int, Object) almacenaba los objetos en un mapa estático, donde los valores estaban fuertemente referenciados. Esto significa que si el objeto contiene referencias que apuntan al contexto, el contexto (que apunta a casi todo lo demás) se filtrará. Si pasa una vista, la vista proporciona una referencia al contexto que la creó. Del mismo modo, los titulares de vistas suelen contener una vista, y los cursores a veces también están asociados con vistas.

Andrei Buneyeu
fuente
2
Gracias, muy útil! ... ¿Sabes si lo que está en la etiqueta se restaura entre las actividades recreativas?
Gunar
25

Podemos usar setTag()y getTag()establecer y obtener objetos personalizados según nuestros requisitos. El setTag()método toma un argumento de tipo Objecty getTag()devuelve un Object.

Por ejemplo,

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

Para los desarrolladores web, esto parece ser el equivalente a datos ...

Oren
fuente
14

Esto es muy útil para ArrayAdapteruso personalizado . Es algún tipo de optimización. Se setTagusa como referencia al objeto que hace referencia en algunas partes del diseño (que se muestra en ListView) en lugar 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
fuente
13

A diferencia de los ID, las etiquetas no se utilizan para identificar vistas. Las etiquetas son esencialmente una información adicional que se puede asociar con una vista. Se utilizan con mayor frecuencia como una conveniencia para almacenar datos relacionados con vistas en las vistas en sí, en lugar de colocarlos en una estructura separada.

Referencia: http://developer.android.com/reference/android/view/View.html

Saad Bilal
fuente
11

La configuración de TAG es realmente útil cuando tiene un ListView y desea reciclar / reutilizar las vistas. De esa manera, ListView se está volviendo muy similar al RecyclerView más nuevo.

@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;
}

fuente