android view android-view android-viewholder

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



view android-view (8)

A diferencia de las ID, las etiquetas no se usan para identificar vistas. Las etiquetas son esencialmente una información adicional que puede asociarse con una vista. La mayoría de las veces se utilizan como una conveniencia para almacenar datos relacionados con las vistas en las vistas en lugar de colocarlos en una estructura separada.

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

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

¿Tengo razón al pensar que puedo asociar cualquier número de objetos con una sola Vista?


Digamos que generas un montón de vistas que son similares. Puede establecer un OnClickListener para cada vista individualmente:

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

Luego, debe crear un método onClick ú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 onClick solo tiene un parámetro, una View , y tiene que obtener otra información de las variables de instancia o las variables locales finales en los ámbitos delimitados. Lo que realmente queremos es obtener información de las vistas en sí .

Introduzca 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()); } };

Es básicamente una manera para que las vistas tengan recuerdos .


El código se agregó y la imagen se agregó a la base de datos. No pude consultarla ni mostrarla desde la base de datos. Puede ayudar. Gracias

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); open_btn = (Button) findViewById(R.id.open); save_btn = (Button) findViewById(R.id.save); open_Img = (ImageView) findViewById(R.id.openImage); saveImg = (ImageView) findViewById(R.id.saveImage); } public void save(View view) { Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(i, 100); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 100 && resultCode == RESULT_OK) { Uri uri = data.getData(); saveImg.setImageURI(uri); bitmap = ((BitmapDrawable)saveImg.getDrawable()).getBitmap(); byteArrayOutputStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG,100,byteArrayOutputStream); encodeImage = Base64.encodeToString(byteArrayOutputStream.toByteArray(),Base64.DEFAULT); } } public void open(View view) { byte[] bytes =Base64.decode(encodeImage,Base64.DEFAULT); Bitmap decodBitmap = BitmapFactory.decodeByteArray(bytes,0,bytes.length); open_Img.setImageBitmap(decodBitmap); }


Esto es muy útil para usar ArrayAdapter personalizado. Es una especie de optimización. Allí se usó setTag 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); } .................... }


La configuración de los TAG es realmente útil cuando tiene un ListView y desea reciclar / reutilizar las vistas. De esa manera, el 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; }


Me gustaría añadir algunas palabras.

Aunque el uso de get/setTag(Object) parece ser muy útil en el caso particular del patrón de ViewHolder, recomiendo pensar dos veces antes de usarlo en otros casos. Casi siempre hay otra buena solución de diseño.

La razón principal es que el código se vuelve insostenible con bastante rapidez.

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

  • Almacena solo un Object , por lo que requiere getTag cuando quieres obtener la getTag . Puede obtener un bloqueo inesperado más adelante cuando decida cambiar el tipo de objeto almacenado en la etiqueta.

  • Esta es la historia de la vida real. Tuvimos un proyecto bastante grande con muchos adaptadores, operaciones asíncronas con vistas, etc. Un desarrollador decidió set/getTag en su parte del código, pero otro ya había establecido una etiqueta para esta vista. Al final, alguien no pudo encontrar su propia etiqueta y estaba muy confundido. Eso nos costó varias horas encontrar el bicho.

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

Antes de Android 4.0, la implementación de View.setTag (int, Object) almacenaría los objetos en un mapa estático, donde los valores fueron fuertemente referenciados. Esto significa que si el objeto contiene alguna referencia que apunte al contexto, el contexto (que apunta a casi todo lo demás) se perderá. Si pasa una vista, la vista proporciona una referencia al contexto que la creó. De manera similar, los titulares de vista suelen contener una vista y los cursores a veces también están asociados con vistas.


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


Podemos usar setTag() y getTag() para configurar y obtener objetos personalizados según nuestro requisito. El método setTag() toma un argumento de tipo Object , y getTag() devuelve un Object .

Por ejemplo,

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