2009-08-24 20 views
11

Carico i dati da Cursore a listview, ma la mia ListView non è veramente visualizzata "liscia". I dati cambiano quando trascino su e giù sulla scollbar nel mio ListView. E alcuni oggetti sembrano duplicati nella mia lista. Ho un "ListView complesso" (due textview, una imageview) Quindi ho usato newView(), bindView() per visualizzare i dati. Qualcuno può aiutarmi?Come caricare "agevolmente" la Listview in Android

risposta

11

Ti descriverò come ottenere tale problema che hai. Forse questo ti aiuterà.

Così, adattatore lista si dispone di tale codice:

public View getView(int position, View contentView, ViewGroup arg2) 
    { 
     ViewHolder holder; 

     if (contentView == null) { 
      holder = new ViewHolder(); 
      contentView = inflater.inflate(R.layout.my_magic_list,null); 
      holder.label = (TextView) contentView.findViewById(R.id.label); 
      contentView.setTag(holder); 
     } else { 
      holder = (ViewHolder) contentView.getTag(); 
     } 

     holder.label.setText(getLabel()); 

     return contentView; 
    } 

Come potete vedere, abbiamo impostato il valore elemento della lista solo dopo aver recuperato titolare.

Ma se si sposta il codice in precedenza if:

holder.label.setText(getLabel()); 

in modo che si prenderà cura come di seguito:

if (contentView == null) { 
    holder = new ViewHolder(); 
    contentView = inflater.inflate(R.layout.my_magic_list,null); 
    holder.label = (TextView) contentView.findViewById(R.id.label); 
    holder.label.setText(getLabel()); 
    contentView.setTag(holder); 
} 

avrete il vostro comportamento dell'applicazione corrente con elemento della lista di duplicazione.

Forse sarà d'aiuto.

+0

Anche questo aiuta anche. Grazie – Dennie

7

ListView è una bestia difficile.

La tua seconda domanda prima: stai vedendo i duplicati perché ListView riutilizza Views tramite convertView, ma non stai facendo in modo di ripristinare tutti gli aspetti della vista convertita. Assicurarsi che il percorso del codice per convertView!=null imposti correttamente tutti i dati per la vista e che tutto funzioni correttamente.

si vorrà il metodo getView() a guardare più o meno simile al seguente se si sta utilizzando visualizzazioni personalizzate:

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    final MyCustomView v = convertView!=null ? (MyCustomView)convertView : new MyCustomView(); 
    v.setMyData(listAdapter.get(position)); 
    return v; 
} 

Se non stai utilizzando la propria visualizzazione personalizzata, basta sostituire la chiamata a new MyCustomView() con una chiamata a inflater.inflate(R.layout.my_layout,null)

per quanto riguarda la prima domanda, ti consigliamo di guardare TechTalk di Romain sulle prestazioni ListView qui: http://code.google.com/events/io/sessions/TurboChargeUiAndroidFast.html

Dal suo discorso e in ordine di im portanza dalla mia esperienza personale,

  • Usa convertView
  • Se avete le immagini, non scala le immagini al volo. Utilizzare Bitmap.createScaledBitmap per creare una bitmap in scala e inserirla nel vostro punto di vista
  • Utilizzare un ViewHolder quindi non c'è bisogno di chiamare un gruppo di findViewByIds() ogni volta
  • Ridurre la complessità dei punti di vista nel vostro ListView. Le poche visualizzazioni secondarie, meglio è. RelativeLayout è molto meglio a questo che, per esempio, LinearLayout. E assicurati di utilizzarlo se stai implementando visualizzazioni personalizzate.
+0

Siamo spiacenti, ma uso newView(), bindView() per visualizzare i dati. è lo stesso problema? – Dennie

+0

Penso di trovare qualcosa di utile con il video, grazie per la condivisione! – Dennie

1

che sto di fronte a questo problema pure, ma nel mio caso ho usato le discussioni per andare a prendere le immagini esterne. È importante che il thread corrente in esecuzione non cambi l'imageView se viene riutilizzato!

public View getView(int position, View vi, ViewGroup parent) { 
ViewHolder holder; 
String imageUrl = ...; 

if (vi == null) { 
    vi = inflater.inflate(R.layout.tweet, null); 
    holder = new ViewHolder(); 
    holder.image = (ImageView) vi.findViewById(R.id.row_img); 
    ... 
    vi.setTag(holder); 
} else { 
    holder = (ViewHolder) vi.getTag();  
} 
holder.image.setTag(imageUrl); 
... 
DRAW_MANAGER.fetchDrawableOnThread(imageUrl, holder.image); 
} 

E poi sul filo recupero che sto facendo il importante controllo:

final Handler handler = new Handler() { 
@Override 
public void handleMessage(Message message) { 
    // VERY IMPORTANT CHECK 
    if (urlString.equals(url)) 
     imageView.setImageDrawable((Drawable) message.obj); 
}; 

Thread thread = new Thread() { 

@Override 
public void run() { 
    Drawable drawable = fetchDrawable(urlString); 
    if (drawable != null) { 
     Message message = handler.obtainMessage(1, drawable); 
     handler.sendMessage(message); 
    } 
}}; 
thread.start(); 

si potrebbe anche annullare il thread corrente se il loro punto di vista è riutilizzato (come è descritto here), ma ho deciso contro questo perché voglio riempire il mio cache per riutilizzarlo in seguito.

0

È possibile visualizzare il testo ricorrente in più righe se lo si gestisce in modo errato. Ne ho parlato un po 'di recente - vedi here. Oltre a questo si potrebbe voler dare un'occhiata a ListView performance optimization. Generalmente è a causa del riutilizzo della vista e l'ho già visto poche volte.

1

Un solo consiglio: non utilizzare MAI lo sfondo trasparente del layout degli articoli: rallenta notevolmente le prestazioni

Problemi correlati