2013-07-17 3 views
20

Sto cercando di implementare una lista di scroll senza fine ma quando chiamo notifyDataSetChanged() l'intera lista si aggiorna, quindi la posizione di scorrimento torna all'inizio.notifyDataSetChanged() aggiorna la lista e scorre indietro verso l'alto

È questo il comportamento normale? come posso fare semplicemente aggiungere gli elementi aggiunti senza aggiornare e mantenere la posizione di scorrimento?

+0

puoi pubblicare il tuo codice completo? – yfsx

risposta

51

Tale comportamento non è normale. Senza vedere il tuo codice, posso suggerire quanto segue:

1) Non stai chiamando notifyDataSetChanged() dal thread dell'interfaccia utente. Il modo corretto:

runOnUiThread(new Runnable() { 
    public void run() { 
     adapter.notifyDataSetChanged(); 
    } 
}); 

2) È accidentalmente o non stanno facendo una chiamata a adapter.notifyDataSetInvalidated();

3) Nella scheda si override del metodo adapter.notifyDataSetChanged(); e ha aggiunto le istruzioni per tornare all'inizio

4) Se si utilizza un elenco per popolare l'adattatore, si fornisce ogni volta un nuovo elenco, quindi le impostazioni dell'adattatore vengono aggiornate. Dovresti sempre fornire la stessa lista. Comunque puoi cambiarlo quanto vuoi. Se si sta reimpostando l'uso lista list.clear invece di list = new ArrayList();

Ecco un esempio del mio adattatore:

public class Adapter extends BaseAdapter { 

    private Activity activity; 
    private ArrayList<HashMap<String, String>> data; 
    private static LayoutInflater inflater = null; 
    public ImageLoader imageLoader; 

    public MediaItemAdapter(Activity a, ArrayList<HashMap<String, String>> d) { 
     activity = a; 
     data = d; 
     inflater = (LayoutInflater) activity 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     imageLoader = new ImageLoader(activity.getApplicationContext()); 
    } 

    public int getCount() { 
     return data.size(); 
    } 

    public Object getItem(int position) { 
     return position; 
    } 

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

    public View getView(int position, View convertView, ViewGroup parent) { 
     View vi = convertView; 
     if (convertView == null) { 
      vi = inflater.inflate(R.layout.item_composer, null); 
     } 
     TextView title = (TextView) vi.findViewById(R.id.item_title); // title 
     TextView price = (TextView) vi.findViewById(R.id.price); 


     return vi; 
    } 


} 

Invito a adattatore:

List myList = new ArrayList<HashMap<String, String>>(); 
Adapter ma = new Adapter(this, myList); 

myList può essere vuoto prima dell'inizializzazione adattatore.

Poi fare qualche operazione con la mia lista:

myList.add(someElement); 
ma.notifyDataSetChanged(); 

se è necessario eliminare tutti gli elementi:

myList.clear(); 
ma.notifyDataSetChanged(); 

Tale implementazione è abbastanza senza fine, ho visto più di 15 mila elementi senza alcun problema.

+0

Potete dare un'occhiata a http: // StackOverflow.it/questions/27815882/scroll-position-jumps-to-previous-list-items-while-scrolling-up-in-custom-listvi – kittu88

+0

Nel mio caso era il terzo problema. Stavo compilando un elenco nuovo di zecca e assegnandolo alla variabile originariamente utilizzata con l'adattatore a causa della quale elenco all'interno dell'adattatore non veniva mai aggiornato. – Nashe

+0

Ottimo post! Salvato la mia sanità mentale! – siniux

6

si può fare in un altro modo, come questo

int position = scrollView.getSelectedItemPosition(); 
notifyDataSetChanged(); 
scrollView.setSelection(position); 
+2

Non è la strada giusta ma a volte è molto utile! – Kasas

2

Se l'adattatore è in sottoclasse , chiamare adapter.clear() chiamerà notifyDataSetChanged() causando la perdita della posizione di scorrimento. Valuta prima di chiamare setNotifyOnChange(false) per impedirlo.

Maggiori informazioni qui: https://stackoverflow.com/a/14719538/383761

5

Nel mio caso il problema era che mi stava chiamando ListView.setAdapter(adapter) ogni volta che nuovi dati sono stati impostati, che azzerare anche la posizione e la vista saltò verso l'alto.

La rimozione delle chiamate ridondanti setAdapter(...) ha risolto il problema.