Metodi getViewTypeCount e getItemViewType di ArrayAdapter


159

Qualcuno in parole semplici può spiegarmi l'uso getViewTypeCount()e i getItemViewType()metodi di ArrayAdapter?

Risposte:


308

Gestiscono il caso in cui desideri tipi diversi di visualizzazione per righe diverse. Ad esempio, in un'applicazione di contatti potresti volere che anche le righe abbiano le immagini sul lato sinistro e le righe dispari abbiano le immagini sul lato destro. In tal caso, useresti:

@Override
public int getViewTypeCount() {
    return 2;
}

@Override
public int getItemViewType(int position) {
    return position % 2;
}

Il framework utilizza il tipo di visualizzazione per decidere quali visualizzazioni passare convertViewnel getViewmetodo . In altre parole, nell'esempio sopra, le tue righe pari otterranno solo viste riciclate con le immagini sul lato sinistro da riutilizzare e le righe dispari otterranno solo quelle con le immagini sulla destra.

Se ogni riga del tuo elenco ha lo stesso layout, non devi preoccuparti dei tipi di visualizzazione. In effetti, BaseAdapter.java fornisce un comportamento predefinito per tutti gli adattatori:

public int getItemViewType(int position) {
    return 0;
}

public int getViewTypeCount() {
    return 1;
}

Questo in effetti ti fornisce lo stesso tipo di vista per ogni riga.

Modifica - per delineare il flusso generale:

  1. Si vincolano i dati AdapterViewutilizzando un adattatore.
  2. Il AdapterViewtentativo di visualizzare gli elementi che sono visibili all'utente.
  3. Il framework richiede la getItemViewTyperiga n, la riga che sta per visualizzare.
  4. Il framework controlla il pool di viste riciclate per le viste del ntipo di riga . Non ne trova perché nessuna vista è stata ancora riciclata.
  5. getViewviene chiamato per la riga n.
  6. Chiama getItemViewTypeper la riga nper determinare quale tipo di vista dovresti usare.
  7. Si utilizza un'istruzione if / switch per gonfiare un file XML diverso a seconda del tipo di vista richiesto.
  8. Riempi la vista con informazioni.
  9. Restituisci la vista, uscendo getViewe la vista della tua riga viene visualizzata per l'utente.

Ora, quando una vista viene riciclata scorrendo fuori dallo schermo, passa in un pool di viste riciclate gestito dal framework. Questi sono essenzialmente organizzati in base al tipo di vista in modo che una vista del tipo corretto sia fornita nel convertViewparametro nel getViewmetodo:

  1. Il framework richiede nuovamente getItemViewTypela riga che desidera visualizzare.
  2. Questa volta, c'è una vista nel pool riciclato del tipo appropriato.
  3. La vista riciclata viene passata come convertViewparametro al getViewmetodo.
  4. Riempi la vista riciclata con nuove informazioni e la restituisci.

1
@Matthew, grazie per la tua risposta. Puoi descrivere il flusso come vengono invocati questi metodi. Inoltre non capisco come questo sia effettivamente associato ai miei dati in res / layout.
Eugene,

Non esiste un contratto esplicito per il richiamo di questi metodi. res / layout è il posto per gli oggetti vista . Si tratta di un adattatore . È necessario controllare il tipo di elemento nel metodo getView e gonfiare la vista corretta da res / layout di conseguenza.
Matthew Willis,

1
Lo stai restituendo tu stesso in getItemViewType.
Matthew Willis,

Si esegue manualmente l'associazione in getView: if (type == 0) {/ * infllate R.layout.row_icon_on_left /} else {/ infllate R.layout.row_icon_on_right * /}
Matthew Willis

75
Attenzione! getItemViewType () deve restituire un int compreso tra 0 e getViewTypeCount () - 1.
PacificSky

12

Se abbiamo bisogno di mostrare diversi tipi di vista nella vista elenco, allora è buono da usare getViewTypeCount()e getItemViewType()nell'adattatore invece di alternare una vista View.GONEe View.VISIBLEpuò essere un'attività molto costosa all'interno della getView()quale influenzerà lo scorrimento dell'elenco.

Controllare questo per l'uso di getViewTypeCount()e getItemViewType()nell'adattatore.

Link: the-use-of-getviewtypecount


La restituzione di IGNORE_ITEM_VIEW_TYPE in getItemViewType () passerà sempre 'view' come null in getView (int position, View view, ViewGroup viewGroup) costringendo a inizializzare tutti i componenti dell'interfaccia utente. Non è un cattivo indicatore di prestazione in cui in caso di modello di supporto, riusciamo a riutilizzare le viste UI esistenti e possiamo semplicemente passare la vista a View.GONE o View.VISIBLE in base alla posizione.
Namrata Bagerwal,

11

Guarda Outttt !!!!
Ho dovuto affrontare un problema nell'implementazione di ListViewieri ed è due tipi di visualizzazioni per le righe che si sono confuse subito dopo averlo fatto scorrere. Anche se la risposta più votata all'interno di questo thread fornisce una buona spiegazione generale, non ha messo in evidenza le informazioni più importanti per fermare il precedente bug dell'interfaccia utente che ho citato.

Ecco la mia spiegazione:
entrambi getViewTypeCount()egetItemViewType() sono utilizzati da BaseAdapter's getViewmetodo per scoprire quale tipo di vista dovrebbe essere recuperare, riciclati e restituiti. (come spiegato nella risposta in alto all'interno della discussione). Ma se non si implementano questi due metodi in modo intuitivo in base al documento API di Android, è possibile che si verifichi il problema di cui ho parlato.

Sintetica Direttiva per l'attuazione:
Per implementare diversi tipi di Viewsper ListView's righe dobbiamo attuare essenzialmente, getItemViewType()egetViewTypeCount() metodi. E la getItemViewType()documentazione ci fornisce una nota come segue:

Nota: I numeri interi deve essere nel range 0di getViewTypeCount() - 1. IGNORE_ITEM_VIEW_TYPEpuò anche essere restituito.

Quindi, nel tuo getItemViewType()caso dovresti restituire i valori per Tipo di vista, a partire da 0, fino all'ultimo tipo come (numero di tipi - 1). Ad esempio, supponiamo che tu abbia solo tre tipi di visualizzazioni? Pertanto, a seconda dell'oggetto dati per la vista, è possibile restituire solo 0 o 1 o 2 dal getItemViewType()metodo, come un indice di array basato su zero. E poiché hai utilizzato tre tipi di visualizzazioni, il tuo getViewTypeCount()metodo deve restituire 3.

In ogni caso, se restituisci altri valori interi come 1, 2, 3 o 111, 222, 333 per questo metodo, potresti sicuramente riscontrare il bug dell'interfaccia utente sopra indicato che hai appena inserito non obbedendo al documento API Android.

Se non hai avuto la minima idea o non hai ancora potuto risolvere e hai bisogno di ulteriori informazioni, leggi il mio risposta dettagliata all'interno di questo thread di domande e risposte StackOverflow .

Leggi il Documento per sviluppatori Android per per ulteriori informazioni che potresti trovare direttamente l'indizio.

Spero che questa risposta possa essere utile a qualcuno là fuori per risparmiare un sacco di ore !!!

Saluti!!!


1
Grazie per aver menzionato IGNORE_ITEM_VIEW_TYPEche avevo un bug su uno dei miei ListView. Ho usato un ArrayAdapter per inserire una vista composta da 1 immagine e 2 vista di testo. Ho avuto solo un tipo di vista. Ho provato a non sostituire il metodo getItemViewType o a sostituirlo restituendo la posizione o un numero intero hardcoded. In tutti i casi, ho riscontrato duplicati nell'elenco, con comportamenti strani durante lo scorrimento (modifiche ai duplicati). Il ritorno IGNORE_ITEM_VIEW_TYPEnel metodo ha risolto il problema. Grazie.
Alex

@Alex felice che ti sia stato utile! :-)
Randika Vishman,
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.