2012-06-25 15 views
19

Ogni articolo nel mio ListView containt un ImageView e un TextView, questo sarà riempito con informazioni remote.Ancora un altro getView chiamato più volte

Ho ricevuto un URL per lo ImageView, pertanto avvio uno AsyncTask che scarica l'immagine e chiamerà setImageBitmap con la bitmap scaricata.

Questo va molto bene ma quando viene creato il ListView, lo getView() viene chiamato spesso. Chiama circa 7 volte lo getView per le prime 10 righe (solo 7 visibili). (Quindi: 0, 1, ecc, 10, 0, 1 ecc.).

Quindi posso semplicemente scorrere senza problemi fino al decimo elemento. Ma dopo, per ogni nuova riga, la listview chiama di nuovo circa 7 volte lo getView per i primi 10 elementi. (Ciò causerà lag ..)

Ma quando rimuovo lo setImageBitmap da AsyncTask, tutto questo non accadrà!

Quale potrebbe essere il problema? Potrebbe essere che un layout sia troppo grande e causerà un'altra serie di getViews?

Qui po 'di codice:

<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" /> 

L'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); 

Qualche informazione in più:

Quando si crea una vista nuova la spettacolo stacktrace n il GetView è stato chiamato da ListView.makeAndAddView() Ma nella striscia inutile getViews è venuta da ListView.measureHeigthOfChildren()

Così sembra che il layout è cambiato quando ho impostato il bitmap ...

+0

sì sembra così anche io credo che il genitore dovrebbe ri-layout di esso auto quando l'immagine ottenere aggiunto come altezza genitore ottiene anche effettuata da that..But questo è quello che io non pensavo certo .. –

risposta

32

il problema era nel Layout del ListView.

Il parametro layout_width è stato impostato su wrap_content quando ho cambiato in fill_parent il problema è scomparso ...

+2

Grazie per questo. Ha funzionato al 100%. – Ron

+0

Ha funzionato anche per me. Mi chiedo se è legato alla dimensione intrinseca di un listView limitato se corrisponde al suo genitore invece di riempirlo? Un listView più grande chiamerebbe logicamente getView() più spesso poiché ci sono più singoli elementi disponibili. –

+1

Nel mio caso, getView veniva chiamato per una posizione ripetutamente e infinitamente anche se quella particolare posizione non era niente di speciale. Ho avuto più tipi di visualizzazione nello stesso modo e un altro tipo di vista. Il problema era che avevo più elementi in un layout e uno degli elementi aveva larghezza determinata da layoutWeight = "1" per occupare spazio rimanente dopo altri widget. Riorganizzare ciò a larghezze fisse ha risolto il problema. – velis

2

Il problema è che il tuo ListView non sa quale sia l'elemento di ogni oggetto. Durante l'inizializzazione, ListView misurerà tutti i suoi figli e si attirerà su queste informazioni. Quello che stai facendo con il tuo AsyncTask, sta cambiando le dimensioni degli elementi nell'elenco e non permettendo a ListView di disegnarsi di nuovo completamente. Ciò comporta il tuo ListView a comportarsi stranamente.

Soluzione: Si consiglia di aggiornare il tuo ListView notificando l'adattatore utilizzando notifyDataSetChanged() nel postExecute del vostro AsyncTask. Ciò consentirà a ListView di disegnarsi con le nuove informazioni.

Spero che funzioni!

Qualche link servizievoli:

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

Lazy load of images in ListView

+0

un'occhiata a questo link: http://stackoverflow.com/a/5092426/929075 notifyDataSetChanged non aiuta quando voglio aggiornare solo una vista. Non sto cambiando l'ArrayList –

0

Ci scusiamo per ritardo di risposta. Ho dovuto affrontare lo stesso problema nel mio adattatore per il widget della galleria. Ho utilizzato Universal Image Loader. La soluzione di Martijn ha funzionato per me. Quello che dovevo fare era aggiungere notifyDataSetChanged() quando l'immagine era stata completamente scaricata e si stava impostando imageView.

0

Ho provato a utilizzare fill_parent come altezza in ListView ma non sono riuscito a ottenerlo perfetto ma come mai l'ho provato impedendo la creazione di convertViews se è già esistente. funziona bene nel mio appoach.

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