2012-06-25 7 views
19

Jedes Element in meinem ListView enthält ein ImageView und ein TextView, wird dies mit Remote-Informationen gefüllt werden.Noch ein getView mehrfach aufgerufen

Ich habe eine URL für die ImageView, daher starte ich eine AsyncTask, die das Bild herunterlädt und setImageBitmap mit der heruntergeladenen Bitmap aufrufen wird.

Das geht sehr gut, aber wenn die ListView erstellt wird, wird die getView() oft aufgerufen. Es ruft etwa 7 Mal die getView für die ersten 10 Zeilen (nur 7 sichtbar). (Also: 0, 1, usw., 10, 0, 1 usw.).

Dann kann ich einfach bis zum zehnten Element scrollen. Aber danach ruft die Listview für jede neue Zeile erneut etwa das 7-fache der getView für die ersten 10 Elemente auf. (Dies wird Lag verursachen ..)

Aber wenn ich die setImageBitmap aus der AsyncTask entfernen, wird dies alles nicht passieren!

Was könnte das Problem sein? Könnte es sein, dass ein Layout zu groß ist, was zu einer weiteren Folge von getViews führt?

Hier einige Code:

<ListView 
    android:id="@+id/mylist" 
    android:layout_width="wrap_content" 
    android:layout_height="fill_parent" 
    android:layout_alignParentBottom="true" 
    android:layout_below="@+id/mydivider" 
    android:divider="@+color/mycolor" 
    android:dividerHeight="2dp" 
    android:fadingEdge="none" 
    android:fastScrollEnabled="true" 
    android:listSelector="@android:color/transparent" 
    android:scrollbars="horizontal" 
    android:scrollingCache="false" 
    android:smoothScrollbar="false" /> 

Die AsyncTask:

public static class MyTask extends AsyncTask<String, Integer, Bitmap> { 
    private LruCache<String, Bitmap> mMap; 
    private String mUri; 
    private int mPosition; 
    private ViewHolder mHolder; 

    public MyTask (ViewHolder holder, int position, LruCache<String, Bitmap> map) { 
     mMap = map; 
     mHolder = holder; 
     mPosition = position; 
    } 

    @Override 
    protected Bitmap doInBackground(String... url) { 
     mUri = url[0]; 
     return getBitmapFromURL(mUri); 
    } 

    @Override 
    protected void onPostExecute(Bitmap b) { 
     if (b != null) { 
      mMap.put(mUri, b); 
      if (mPosition == mHolder.position) { 
       holder.image.setImageBitmap(b); 
      } 
     } 
    }; 
} 

getView()

row = convertView; 
ViewHolder holder; 
if (row == null) { 
    row = vi.inflate(R.layout.mylayout, null); 
    holder = new ViewHolder(); 
    holder.image = (ImageView) row.findViewById(R.id.myimage); 
    holder.title = (TextView) row.findViewById(R.id.mytext); 
    row.setTag(holder); 
} else { 
    holder = (ViewHolder) row.getTag(); 
} 

holder.title.setText("text"); 
holder.image.setImageResource(R.drawable.mydefaulticon); 
holder.position = position; 
startMyTask(content, holder, position); 

Mehr Informationen:

Wenn eine neue Ansicht erstellt die Stacktrace anzeigen n die getView wurde von ListView.makeAndAddView() Aber in der nutzlosen Strähne GetViews nannte es herkommt ListView.measureHeigthOfChildren()

So scheint es, wie das Layout geändert wird, wenn ich die Bitmap gesetzt ...

+0

ja sieht so auch ich glaube, die Eltern sollen mich dies durch that..But bewirkt bekommt als Mutter Höhe hinzukommen, was nicht daran gedacht, sicher .. –

Antwort

32

Das Problem war, in das Layout der Listview.

Der Parameter layout_width wurde wrap_content gesetzt, wenn ich es fill_parent das Problem verschwunden geändert ...

+2

Danke dafür. 100% gearbeitet. – Ron

+0

Auch für mich gearbeitet. Ich frage mich, ob es sich auf die inhärente Größe einer ListView bezieht, die begrenzt ist, wenn sie mit ihrer Eltern übereinstimmt, anstatt sie zu füllen? Ein größeres listView würde getView() logischerweise häufiger aufrufen, da mehr einzelne Elemente verfügbar sind. –

+1

In meinem Fall wurde getView für eine Position wiederholt und unendlich aufgerufen, obwohl diese bestimmte Position nichts Besonderes war. Ich hatte mehrere Ansichtsarten genau so auf demselben Bildschirm wie auf einem anderen Ansichtstyp. Das Problem war, dass ich mehrere Elemente in einem Layout hatte und eines der Elemente die von layoutWeight = "1" festgelegte Breite hatte, um den verbleibenden Platz nach anderen Widgets zu übernehmen. Das Umstellen auf feste Breiten löste das Problem. – velis

2
verwenden

Das Problem ist, dass Ihr ListView nicht weiß, was die einzelnen Elemente sind. Bei der Initialisierung misst das ListView alle seine untergeordneten Objekte und zeichnet sich selbst anhand dieser Informationen auf. Was Sie mit Ihrer AsyncTask tun, ist, die Größe der Elemente in der Liste zu ändern und die ListView sich nicht vollständig neu zeichnen zu lassen. Dies führt zu einem strikten Verhalten Ihres ListView.

Lösung: Sie sollten Ihren ListView aktualisieren, indem Sie den Adapter unter Verwendung von notifyDataSetChanged() im PostExecute Ihrer AsyncTask benachrichtigen. Dadurch kann sich der ListView mit den neuen Informationen selbst zeichnen.

Ich hoffe, es funktioniert!

Einige weiterführende Links:

http://thinkandroid.wordpress.com/2012/06/13/lazy-loading-images-from-urls-to-listviews/

Lazy load of images in ListView

+0

Blick auf diesem Link erneut Layout, wenn Bild, um es selbst auch: http://stackoverflow.com/a/5092426/929075 notifyDataSetChanged wird nicht helfen, wenn ich nur eine Ansicht nur aktualisieren möchte. Ich ändere nicht die ArrayList –

0

Sorry für späte Antwort. Ich hatte das gleiche Problem in meinem Adapter für Galerie-Widget. Ich hatte Universal Image Loader eingesetzt. Martijns Lösung funktionierte für mich. Alles, was ich tun musste, war hinzuzufügen notifyDataSetChanged(), wenn das Bild vollständig heruntergeladen und ImageView eingestellt wurde.

0

Ich habe versucht, fill_parent als Höhe in ListView zu verwenden, aber ich konnte es nicht perfekt erreichen, aber wie auch immer ich es probierte, indem ich das Erstellen von convertViews verhinderte, wenn es bereits existiert. Es funktioniert gut in meinem Beruf.

 @Override 
     public View getView(final int position, View convertView, ViewGroup parent) { 
     if (convertView != null) 
      return convertView; 
     else { 
      //your code... 
     } 
    } 
Verwandte Themen