2010-06-25 25 views
9

Si verificano problemi con il codice di BaseAdapter adattato da un libro. Sto usando le varianti di questo codice dappertutto nella mia applicazione, ma appena realizzato quando si scorre un lungo elenco gli elementi in ListView diventano confusi e non tutti gli elementi vengono visualizzati.BaseAdapter che provoca l'eliminazione dell'ordine di ListView durante lo scorrimento

È molto difficile descrivere il comportamento esatto, ma è facile vedere se si prende una lista ordinata di 50 articoli e si inizia a scorrere su e giù.

class ContactAdapter extends BaseAdapter { 

    ArrayList<Contact> mContacts; 

    public ContactAdapter(ArrayList<Contact> contacts) { 
     mContacts = contacts; 
    } 

    @Override 
    public int getCount() { 
     return mContacts.size(); 
    } 

    @Override 
    public Object getItem(int position) { 
     return mContacts.get(position); 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View view; 
     if(convertView == null){ 
      LayoutInflater li = getLayoutInflater(); 
      view = li.inflate(R.layout.groups_item, null); 
      TextView label = (TextView)view.findViewById(R.id.groups_item_title); 
      label.setText(mContacts.get(position).getName()); 
      label = (TextView)view.findViewById(R.id.groups_item_subtitle); 
      label.setText(mContacts.get(position).getNumber()); 
     } 
     else 
     { 
      view = convertView; 
     } 
     return view; 
    } 

} 

risposta

12

Si stanno inserendo solo i dati nei widget TextView quando vengono creati per la prima volta. È necessario spostare queste quattro linee:

 TextView label = (TextView)view.findViewById(R.id.groups_item_title); 
     label.setText(mContacts.get(position).getName()); 
     label = (TextView)view.findViewById(R.id.groups_item_subtitle); 
     label.setText(mContacts.get(position).getNumber()); 

di essere dopo il blocco if/else e prima del ritorno metodo, in modo da aggiornare i TextView widget se si Riciclaggio della riga o la creazione di uno nuovo.

+0

Oh, capisco. Quindi ListView contiene solo al massimo il numero di visualizzazioni necessarie per riempire lo schermo? –

+0

@Mr. Ambiguo: più o meno. Può memorizzare una coppia in cache per poter reagire rapidamente per scorrere le richieste. Tuttavia, in un 'ListView' con spazio UI per 10 righe e un' Adapter' di 1.000 righe, il numero di 'Views' sarà molto più vicino a 10 di 1,000. Probabilmente come 12 o 14. Questo è il punto di riciclo delle righe con 'convertView', quindi Android non deve creare (e successivamente GC) un intero pasticcio di widget di riga. – CommonsWare

5

per chiarire ulteriormente la risposta del CommonsWare, ecco qualche informazione in più:

Il li.inflate funzionamento (necessario qui per l'analisi del layout di una riga da XML e creare l'oggetto View appropriato) è avvolto da un se (convertView == null) dichiarazione di efficienza, quindi l'inflazione dello stesso oggetto non accadrà più e più volte ogni volta che appare in vista.

TUTTAVIA, le altre parti del metodo getView vengono utilizzate per impostare altri parametri e, pertanto, NON devono essere incluse nella riga if (convertView == null) {} ... else {}.

In molti comuni implementazione di questo metodo, alcuni elementi dell'etichetta textView, ImageView o ImageButton devono essere popolato da valori dall'elenco [posizione], utilizzando findViewById e dopo che .setText o .setImageBitmap operazioni . Queste operazioni devono arrivare dopo entrambe creando una vista da zero con l'inflazione e ottenendo una vista esistente se non null (ad esempio su un aggiornamento).

Un altro buon esempio in cui viene applicata questa soluzione per un controllo ListView ArrayAdapter appare in https://stackoverflow.com/a/3874639/978329

Problemi correlati