web-dev-qa-db-de.com

die getView-Methode des benutzerdefinierten Listview-Adapters wird mehrmals aufgerufen und ist nicht zusammenhängend

Ich habe einen benutzerdefinierten Listenadapter:

class ResultsListAdapter extends ArrayAdapter<RecordItem> {

in der überschriebenen 'getView'-Methode prüfe ich, welche Position ist und ob es sich um eine convertView handelt oder nicht:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        System.out.println("getView " + position + " " + convertView);

Die Ausgabe davon (wenn die Liste zum ersten Mal angezeigt wird, noch keine Benutzereingabe)

04-11 16:24:05.860: INFO/System.out(681): getView 0 null  
04-11 16:24:29.020: INFO/System.out(681): getView 1 [email protected]  
04-11 16:25:48.070: INFO/System.out(681): getView 2 [email protected]  
04-11 16:25:49.110: INFO/System.out(681): getView 3 [email protected]  
04-11 16:25:49.710: INFO/System.out(681): getView 0 [email protected]  
04-11 16:25:50.251: INFO/System.out(681): getView 1 null  
04-11 16:26:01.300: INFO/System.out(681): getView 2 null  
04-11 16:26:02.020: INFO/System.out(681): getView 3 null  
04-11 16:28:28.091: INFO/System.out(681): getView 0 null  
04-11 16:37:46.180: INFO/System.out(681): getView 1 [email protected]  
04-11 16:37:47.091: INFO/System.out(681): getView 2 [email protected]  
04-11 16:37:47.730: INFO/System.out(681): getView 3 [email protected]  

AFAIK, obwohl ich es nicht explizit finden konnte, wird getView () nur für sichtbare Zeilen aufgerufen. Da meine App mit vier sichtbaren Zeilen beginnt, macht zumindest das Positionsnummernwechseln von 0-3 einen Sinn. Aber der Rest ist ein Durcheinander:

  • Warum wird getview für jede Zeile dreimal aufgerufen? 
  • Woher kommen diese convertViews, wenn ich noch nicht gescrollt habe?

Ich habe etwas recherchiert und ohne eine gute Antwort zu erhalten, habe ich bemerkt, dass die Leute dieses Problem mit Layoutproblemen in Verbindung bringen. Für den Fall, hier ist das Layout, das die Liste enthält:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_height="fill_parent"
    Android:layout_width="fill_parent" 
    Android:orientation="vertical" >

    <TextView Android:id="@+id/pageDetails"
        Android:layout_width="fill_parent" 
        Android:layout_height="wrap_content" />

    <ListView Android:id="@+id/list"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content" 
        Android:drawSelectorOnTop="false" />

</LinearLayout>

und das Layout jeder einzelnen Reihe:

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="fill_parent"
Android:layout_height="108dp"    
Android:padding="4dp">

<ImageView
    Android:id="@+id/thumb"        
    Android:layout_width="120dp"
    Android:layout_height="fill_parent"        
    Android:layout_alignParentTop="true"
    Android:layout_alignParentBottom="true"
    Android:layout_alignParentLeft="true"
    Android:layout_marginRight="8dp"        
    Android:src="@drawable/loading" />

<TextView  
    Android:id="@+id/price"
    Android:layout_width="wrap_content"
    Android:layout_height="18dp"         
    Android:layout_toRightOf="@id/thumb"
    Android:layout_alignParentBottom="true"       
    Android:singleLine="true" />

<TextView  
    Android:id="@+id/date"
    Android:layout_width="wrap_content"
    Android:layout_height="18dp"         
    Android:layout_alignParentBottom="true"
    Android:layout_alignParentRight="true" 
    Android:paddingRight="4dp"       
    Android:singleLine="true" />

<TextView
    Android:id="@+id/title"
    Android:layout_width="fill_parent"
    Android:layout_height="wrap_content"
    Android:textSize="17dp" 
    Android:layout_toRightOf="@id/thumb"
    Android:layout_alignParentRight="true"
    Android:layout_alignParentTop="true"
    Android:paddingRight="4dp"   
    Android:layout_alignWithParentIfMissing="true"
    Android:gravity="center" />

</RelativeLayout>

Vielen Dank für Ihre Zeit

154
edzillion

Dies ist kein Problem, es gibt absolut keine Garantie für die Reihenfolge, in der getView() aufgerufen wird oder wie oft. In Ihrem speziellen Fall tun Sie mit einer ListView das Schlimmste, indem Sie einen height=wrap_content angeben. Dies zwingt ListView, zum Layout-Zeitpunkt einige Kinder aus dem Adapter heraus zu messen, um zu wissen, wie groß er sein sollte. Dies ist, was ListView mit der convertViews versorgt, die an getView() übergeben wird, sogar bevor Sie einen Bildlauf durchführen.

263
Romain Guy

Versuchen Sie es mit match_parent in der layout_height-Eigenschaft der Listenansicht. Dadurch wird verhindert, dass getView() so oft aufgerufen wird.

53
Fred T

Ich habe dieses Problem behoben, als ich sowohl layout_width als auch layout_height in match_parent geändert habe (das Ändern von layout_height half nicht).


Hilfreiche Hinweise Achtung, wenn Sie Objekte verschachtelt haben. Sie müssen das "höchste" in match_parent ändern. Hoffe es hilft jemandem.

45
Eugene Chumak

Ich kann Ihre "Warum" -Frage nicht beantworten, aber ich habe definitiv eine Lösung für das Problem des irritierenden "ListView-Elements, das" wiederholt (wenn Sie Elemente in Ihrer Sammlung haben, die größer als die Bildschirmhöhe sind).

Wie bereits erwähnt, behalten Sie die Android: layout_height - Eigenschaft des ListVew -Tags als fill_parent.

In Bezug auf die getView () - Funktion besteht die Lösung darin, eine static-Klasse mit dem Namen ViewHolder zu verwenden. Check out das Beispiel. Es führt erfolgreich die Aufgabe aus, alle Elemente in ur Array oder ArrayCollection hinzuzufügen.

Hoffe das hilft Freunden !!

Beste Grüße, Siddhant

7
Siddhant

Fragen: Warum ruft der Adapter oft getView () auf? Ans: Wenn ListView beim Scrollen rendert, wird die Ansicht mit den nächsten anstehenden Ansichten aktualisiert, beispielsweise für Welcher Adapter benötigt Ansichten, um getView () aufzurufen.

Fragen: Warum werden weniger Anrufe aufgerufen, wenn Breite und Höhe der Listenansicht auf fill_parent eingestellt sind? Ans: Da der Inflator die feste Größe für den Bildschirmbereich für die Liste hat, berechnet er einmal für Rendern der Ansichten auf dem Bildschirm.

Ich hoffe, es wird Ihre Anfrage lösen.

4
jitain sharma

Ich hatte das gleiche Problem mit dem Dropdown in einer AutoCompleteTextView. Ich habe zwei Tage lang mit dem Problem gekämpft, bis ich hier ankomme und Sie mir die Lösung zeigen.

Wenn ich dropDownHeight = "match_parent" schreibe, ist das Problem behoben. Das Problem hängt jetzt mit der Benutzeroberfläche zusammen (wenn Sie einen Eintrag haben, ist die Dropdown-Liste zu groß), aber das Problem mehrerer Anrufe (viel wichtiger) ist behoben.

Vielen Dank!!

Ich habe das gleiche Problem. Wenn ich height auf fill_parent gesetzt habe, dann bekomme ich "normalerweise" 2 Aufrufe pro Zeile. Wenn ich jedoch die Höhe meiner ListView auf den exakten Wert, beispielsweise 300dp, setze, bekomme ich genau einen GetView-Aufruf pro Zeile. 

Es scheint mir also, dass der einzige Weg darin besteht, zuerst die Höhe des Bildschirms zu bestimmen und dann die Höhe des Listenwerts auf diesen Wert programmgesteuert einzustellen. Ich mag es nicht Ich hoffe es gibt einen besseren Weg.

2
bobetko

"Warum wird getview für jede Zeile dreimal aufgerufen?" Weil getView aufgerufen wird, wenn Sie in der Listenansicht scrollen, und besser gesagt, dass es aufgerufen wird, wenn die Position einer Ansicht Ihrer Liste geändert wird!

2
Ungureanu Liviu

Für alle, die noch (nachdem Sie die height der ListView auf match_parent gesetzt haben) festsitzen (wie ich es war):

Sie müssen auch die height des übergeordneten Layouts auf match_parent setzen.

Siehe Beispiel unten. Die LinearLayout ist hier das übergeordnete Element:

<LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:orientation="vertical">

        <TextView
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:text="@string/something" />

        <ListView
            Android:id="@+id/friendsList"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent" />
    </LinearLayout>
2
B001ᛦ

ich habe diese Lösung gemacht, vielleicht ist sie nicht die beste, aber sie erledigt die Arbeit ...

//initialize control string
private String control_input = " ";

dann =

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    View gridview = convertView;

    // change input_array for the array you use
    if (!control_input.equals(input_array[position])) {
        control_input = input_array[position];

        //do your magic

    } 

    return gridview;
}

ich hoffe es hilft!

0
yago

Dies kommt möglicherweise zu spät, aber wenn Sie layout_weight verwenden, denken Sie daran, layout_width="0dp" immer einzustellen.

0
Kuti Gbolahan