Qual è lo scopo principale dei metodi di SetTag () getTag () di View?


421

Qual è lo scopo principale di tali metodi come setTag()e getTag()di Viewoggetti tipo?

Ho ragione nel pensare di poter associare un numero qualsiasi di oggetti a una singola vista?

Risposte:


636

Supponiamo che tu generi un gruppo di visualizzazioni simili. È possibile impostare un OnClickListenerper ogni vista singolarmente:

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

Quindi devi creare un onClickmetodo univoco per ogni vista anche se fanno cose simili, come:

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

Questo perché onClickha solo un parametro, a View, e deve ottenere altre informazioni dalle variabili di istanza o variabili locali finali negli ambiti racchiusi. Ciò che vogliamo veramente è ottenere informazioni dalle opinioni stesse .

Inserisci getTag/ setTag:

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

Ora possiamo usare lo stesso OnClickListener per ogni pulsante:

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

Fondamentalmente è un modo per le viste di avere ricordi .


8
@Matthew Willis ma possiamo farlo anche usando view.getId (). non è vero ?
Android Killer,

50
@AndroidKiller potresti, ma con setTag () puoi mettere qualsiasi oggetto tu voglia, anche le classi personalizzate - così puoi usarli per mantenere un riferimento ai dati che la vista sta visualizzando
Daniel

Cosa devo fare se voglio solo cambiare il colore di sfondo del pulsante su cui si fa clic ??? Ricevo la posizione da getTag ().
Sagar Devanga,

2
@Sagar: public void ui_click(View view){ if(20==((int)view.getTag())) view.setBackgroundColor(colorInt); }dovrebbe fare il trucco per la parte a colori. 20 è solo un segnaposto per la posizione di convalida della vista.
RiA

Penso che questo sia alla vecchia maniera. il nuovo modo è usare argomenti generici che forniscano la sicurezza del tipo. ma questo è comunque buono.
M.kazem Akhgary,

124

Vorrei aggiungere qualche parola.

Anche se l'utilizzo get/setTag(Object)sembra essere molto utile nel caso particolare di un modello ViewHolder, consiglierei di pensarci due volte prima di usarlo in altri casi. C'è quasi sempre un'altra soluzione con un design migliore.

Il motivo principale è che un codice del genere diventa insostenibile abbastanza rapidamente.

  • Non è ovvio per altri sviluppatori cosa hai progettato per archiviare come tag nella vista. I metodi setTag/getTagnon sono affatto descrittivi.

  • Memorizza solo un Object, che richiede di essere lanciato quando vuoi getTag. È possibile ottenere arresti anomali imprevisti in seguito quando si decide di modificare il tipo di oggetto memorizzato nel tag.

  • Ecco una storia di vita reale: abbiamo avuto un progetto piuttosto grande con molti adattatori, operazioni asincrone con viste e così via. Uno sviluppatore ha deciso di set/getTaginserire nella sua parte di codice, ma un altro aveva già impostato il tag su questa vista. Alla fine, qualcuno non riuscì a trovare il proprio tag ed era molto confuso. Ci è costato diverse ore per trovare il bug.

setTag(int key, Object tag)sembra molto meglio, perché puoi generare chiavi univoche per ogni tag (usando le risorse ID ), ma c'è una restrizione significativa per Android <4.0. Dai documenti di Lint:

Prima di Android 4.0, l'implementazione di View.setTag (int, Object) memorizzava gli oggetti in una mappa statica, in cui i valori erano fortemente referenziati. Ciò significa che se l'oggetto contiene riferimenti che rimandano al contesto, il contesto (che indica praticamente tutto il resto) perderà. Se si passa una vista, la vista fornisce un riferimento al contesto che l'ha creata. Allo stesso modo, i detentori di una vista in genere contengono una vista e talvolta anche i cursori sono associati alle viste.


2
Grazie, molto utile! ... Ti capita di sapere se ciò che è nel tag viene ripristinato tra le ricreazioni di attività?
Gunar

25

Possiamo usare setTag()e getTag()impostare e ottenere oggetti personalizzati secondo le nostre esigenze. Il setTag()metodo accetta un argomento di tipo Objecte getTag()restituisce un Object.

Per esempio,

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

20

Per gli sviluppatori Web, questo sembra essere l'equivalente dei dati ...


14

Questo è molto utile per l' ArrayAdapterutilizzo personalizzato . È una sorta di ottimizzazione. Viene setTagusato come riferimento all'oggetto che fa riferimento su alcune parti del layout (quella visualizzata in ListView) anziché 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);
    }
            ....................
}

13

A differenza degli ID, i tag non vengono utilizzati per identificare le viste. I tag sono essenzialmente un'informazione aggiuntiva che può essere associata a una vista. Vengono spesso utilizzati per comodità per archiviare i dati relativi alle viste nelle viste stesse anziché inserendoli in una struttura separata.

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


11

L'impostazione dei TAG è davvero utile quando si dispone di un ListView e si desidera riciclare / riutilizzare le visualizzazioni. In questo modo ListView sta diventando molto simile al più recente 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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.