Die Methoden getViewTypeCount und getItemViewType von ArrayAdapter

159

Kann mir jemand in einfachen Worten den Gebrauch getViewTypeCount()und die getItemViewType()Methoden von erklären ArrayAdapter?

Eugene
quelle

Antworten:

308

Diese behandeln den Fall, dass Sie unterschiedliche wollen Typen Sicht für verschiedene Zeilen. In einer Kontaktanwendung möchten Sie möglicherweise, dass gerade Zeilen Bilder auf der linken Seite und ungerade Zeilen Bilder auf der rechten Seite haben. In diesem Fall würden Sie verwenden:

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

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

Das Framework verwendet Ihren Ansichtstyp, um zu entscheiden, über welche Ansichten Sie convertViewin Ihrer getViewMethode übergeben werden . Mit anderen Worten, im obigen Beispiel erhalten Ihre geraden Zeilen nur recycelte Ansichten mit Bildern auf der linken Seite, die wiederverwendet werden können, und ungerade Zeilen erhalten nur solche mit Bildern auf der rechten Seite.

Wenn jede Zeile in Ihrer Liste das gleiche Layout hat, müssen Sie sich keine Gedanken über die Ansichtstypen machen. Tatsächlich bietet BaseAdapter.java ein Standardverhalten für alle Adapter:

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

public int getViewTypeCount() {
    return 1;
}

Auf diese Weise erhalten Sie für jede Zeile den gleichen Ansichtstyp.

Bearbeiten - um den allgemeinen Ablauf zu skizzieren:

  1. Sie binden Daten AdapterViewmit einem Adapter an Ihren .
  2. Es wird AdapterViewversucht, Elemente anzuzeigen, die für den Benutzer sichtbar sind.
  3. Das Framework fordert getItemViewTypeZeile an n, die Zeile, die angezeigt werden soll.
  4. Das Framework überprüft seinen Pool für recycelte Ansichten auf Ansichten des Zeilentyps n. Es werden keine gefunden, da noch keine Ansichten recycelt wurden.
  5. getViewwird für Zeile aufgerufen n.
  6. Sie rufen getItemViewTypenach einer Zeile nauf, um zu bestimmen, welche Art von Ansicht Sie verwenden sollen.
  7. Sie verwenden eine if / switch-Anweisung, um eine andere XML-Datei aufzublasen, je nachdem, welcher Ansichtstyp erforderlich ist.
  8. Sie füllen die Ansicht mit Informationen.
  9. Sie geben die Ansicht zurück, beenden sie getViewund die Ansicht Ihrer Zeile wird dem Benutzer angezeigt.

Wenn eine Ansicht durch Scrollen vom Bildschirm wiederhergestellt wird, wird sie in einen Pool für wiederverwertete Ansichten verschoben, der vom Framework verwaltet wird. Diese sind im Wesentlichen nach Ansichtstyp organisiert, sodass Sie in convertViewParameter in Ihrer getViewMethode eine Ansicht des richtigen Typs erhalten :

  1. Das Framework ruft erneut getItemViewTypedie Zeile auf, die angezeigt werden soll.
  2. Diesmal gibt es einen Blick in den recycelten Pool des entsprechenden Typs.
  3. Die recycelte Ansicht wird Ihnen als convertViewParameter für Ihre getViewMethode übergeben.
  4. Sie füllen die recycelte Ansicht mit neuen Informationen und geben sie zurück.
Matthew Willis
quelle
1
@ Matthew, danke für deine Antwort. Können Sie den Ablauf beschreiben, wie diese Methoden aufgerufen werden? Außerdem verstehe ich nicht, wie dies tatsächlich mit meinen Daten in res / layout zusammenhängt.
Eugene
Es gibt keinen expliziten Vertrag, wann diese Methoden aufgerufen werden. res / layout ist der Ort für Ansichtsobjekte . Dies ist ein Adapter . Sie sollten den Elementtyp in Ihrer getView-Methode überprüfen und die richtige Ansicht aus res / layout entsprechend aufblasen.
Matthew Willis
1
Sie geben es selbst in getItemViewType zurück.
Matthew Willis
Sie führen die Zuordnung manuell in getView durch: if (type == 0) {/ * R.layout.row_icon_on_left /} aufblasen else {/ R.layout.row_icon_on_right aufblasen * /}
Matthew Willis
75
In acht nehmen! getItemViewType () muss ein int zwischen 0 und getViewTypeCount () - 1 zurückgeben.
PacificSky
12

Wenn wir verschiedene Arten von Ansicht in Listenansicht dann seine gut zu bedienen zeigen müssen getViewTypeCount()und getItemViewType()in Adapter statt einer Ansicht Makeln View.GONEund View.VISIBLEkann sehr teuer Aufgabe innerhalb getView()der die Liste blättern beeinflussen.

Bitte überprüfen Sie diese für die Verwendung von getViewTypeCount()und getItemViewType()im Adapter.

Link: die Verwendung von getviewtypecount

Kyogs
quelle
Wenn Sie IGNORE_ITEM_VIEW_TYPE in getItemViewType () zurückgeben, wird 'get' in getView (int position, View view, ViewGroup viewGroup) immer als null übergeben, um alle UI-Komponenten zu initialisieren. Ist das nicht ein schlechter Leistungsindikator, bei dem wir im Falle eines Haltermusters vorhandene Benutzeroberflächenansichten wiederverwenden und die Ansicht je nach Position einfach auf View.GONE oder View.VISIBLE umschalten können?
Namrata Bagerwal
11

Watch Outttt !!!!
Ich hatte ListViewgestern ein Problem mit der Implementierung eines und es gab zwei Arten von Ansichten für Zeilen, die kurz nach dem Scrollen durcheinander gebracht wurden. Obwohl die am häufigsten gewählte Antwort in diesem Thread eine gute allgemeine Erklärung enthält, hat sie nicht die wichtigsten Informationen hervorgehoben, um den oben erwähnten UI-Fehler zu stoppen.

Hier ist meine Erklärung:
Beide getViewTypeCount()und getItemViewType()werden von BaseAdapterder getViewMethode verwendet, um herauszufinden, welcher Typ einer Ansicht abgerufen, recycelt und zurückgegeben werden soll. (wie in der oberen Antwort im Thread erklärt). Wenn Sie diese beiden Methoden jedoch nicht intuitiv gemäß dem Android API Doc implementieren, können Sie auf das von mir erwähnte Problem stoßen.

Zusammenfassende Richtlinie für die Implementierung:
Um mehrere Arten von Viewsfor ListView-Zeilen zu implementieren, müssen im Wesentlichen Methoden getItemViewType()und getViewTypeCount()Methoden implementiert werden. Und die getItemViewType()Dokumentation gibt uns einen Hinweis wie folgt:

Hinweis: Ganzzahlen müssen im Bereich 0bis liegen getViewTypeCount() - 1. IGNORE_ITEM_VIEW_TYPEkann auch zurückgegeben werden.

Daher getItemViewType()sollten Sie in Ihrem Wert Werte für den Ansichtstyp von 0 bis zum letzten Typ als (Anzahl der Typen - 1) zurückgeben. Nehmen wir zum Beispiel an, Sie haben nur drei Arten von Ansichten. Abhängig vom Datenobjekt für die Ansicht können Sie also nur 0 oder 1 oder 2 von der getItemViewType()Methode zurückgeben, wie bei einem nullbasierten Array-Index. Da drei Arten von Ansichten verwendet werden, getViewTypeCount()muss Ihre Methode 3 zurückgeben.

Wenn Sie für diese Methode andere ganzzahlige Werte wie 1, 2, 3 oder 111, 222, 333 zurückgeben, kann auf jeden Fall der oben genannte UI-Fehler auftreten, den Sie gerade platziert haben, indem Sie sich nicht an das Android-API-Dokument halten.

Wenn Sie den Hinweis nicht erhalten haben oder sich noch nicht auflösen konnten und weitere Informationen benötigen, lesen Sie bitte meine ausführliche Antwort in diesem StackOverflow-Q & A-Thread .

Lesen Sie das Android Developer Doc, um weitere Informationen zu erhalten. Möglicherweise finden Sie den Hinweis direkt.

Hoffe, diese Antwort könnte für jemanden da draußen hilfreich sein, um viele Stunden zu sparen !!!

Prost!!!

Randika Vishman
quelle
1
Vielen Dank für die Erwähnung, dass IGNORE_ITEM_VIEW_TYPEich einen Fehler in einer meiner ListView hatte. Ich habe einen ArrayAdapter verwendet, um eine Ansicht einzufügen, die aus 1 Bild- und 2 Textansichten besteht. Ich hatte nur einen Ansichtstyp. Ich habe versucht, die Methode getItemViewType entweder nicht zu überschreiben oder sie zu überschreiben, indem ich die Position oder eine fest codierte Ganzzahl zurückgebe. In allen Fällen traten in meiner Liste Duplikate mit merkwürdigem Verhalten beim Scrollen auf (Änderungen an Duplikaten). Die Rückgabe IGNORE_ITEM_VIEW_TYPEin der Methode hat das Problem behoben. Vielen Dank.
Alex
@ Alex froh, dass es für dich hilfreich war! :-)
Randika Vishman