esempio di NotifyDataSetChanged


166

Sto cercando di utilizzare nel mio Android Applicationil notifyDataSetChanged()metodo per un ArrayAdapterma non funziona per me.

Ho trovato qui una risposta , che notifyDataSetChanged()dovrebbe essere eseguita nel thread principale, ma non c'era alcun esempio per quello.

Qualcuno potrebbe inviare un esempio o almeno un link ?!



puoi controllare questo blog e questo esempio in github e anche in questo
Cabezas,

Risposte:


328

Per una ArrayAdapter, notifyDataSetChangedfunziona solo se si utilizza il add(), insert(), remove(), e clear()sulla scheda.

Quando ArrayAdapterviene costruito, contiene il riferimento per quello Listche è stato passato. Se dovessi passare Listun membro che era un membro di un'attività e cambiare quel membro di attività in un secondo momento, ArrayAdapterè ancora in possesso di un riferimento all'originale List. L'adattatore non sa che è stato modificato Listnell'attività.

Le tue scelte sono:

  1. Utilizzare le funzioni di ArrayAdaptermodificare l'elenco sottostante ( add(), insert(), remove(), clear(), etc.)
  2. Ricreare il ArrayAdaptercon i nuovi Listdati. (Utilizza molte risorse e raccolta dei rifiuti.)
  3. Crea la tua classe derivata BaseAdaptere ListAdapterche consente di modificare la Liststruttura dei dati sottostante .
  4. Utilizzare notifyDataSetChanged()ogni volta che l'elenco viene aggiornato. Per chiamarlo sul thread dell'interfaccia utente, utilizzare runOnUiThread()di Activity. Quindi notifyDataSetChanged()funzionerà.

13
fai anche attenzione ad assegnare "nuovi" oggetti ai tuoi dati. utilizzare clear () invece, ripopolare / apportare modifiche ai dati, quindi chiamare notificationDataSetChanged ()
moonlightcheese

Ma cosa succede se chiamiamo notifyDataSetChanged()in questo modo ((BaseAdapter) arrayAdapter).notifyDataSetChanged();:?
teoREtik,

2
Uso BaseExpandableListAdapter, non ha funzioni add () o remove (), quindi memorizzo la mia mappa come variabile membro. Aggiornamento Map e chiamo notificationDatasetChanged () ma non succede nulla. Quando uso la scelta n. 4, funziona. Perché???
emeraldhieu,

Sto usando ArrayAdapter per GridView personalizzato, sto aggiungendo immagini mentre le ottengo dagli URL chiamando adapter.add (dataReceived). Questo funziona bene aggiunge dati, ma perché è rinfrescante e andare in cima. Voglio mostrare gli elementi che verranno aggiunti senza aggiornare l'elenco. (Quello che voglio fare è lavorare con GridView di Android usando notifyDatasetChanged ()) Come posso farlo funzionare in questo customGridView (StaggeredGridView).
MobileEvangelist,

1
Ho provato a creare il mio BaseAdapter per aggiungere metodi di ordinamento all'elenco, ma per qualche motivo non ha funzionato. Non che la mia app sia lenta anche se creo l'intero adattatore con un array ordinato, ma mi irrita comunque. Ma come farebbe a creare molta spazzatura? Suppongo che l'effettiva matrice di dati costosi venga mantenuta come riferimento nell'attività che chiama l'adattatore, il che significa che verrà raccolto solo l'adattatore.
G_V,

34

È possibile utilizzare il runOnUiThread()metodo come segue. Se non si utilizza a ListActivity, basta adattare il codice per ottenere un riferimento al proprio ArrayAdapter.

final ArrayAdapter adapter = ((ArrayAdapter)getListAdapter());
runOnUiThread(new Runnable() {
    public void run() {
        adapter.notifyDataSetChanged();
    }
});

1
Ho provato ad aggiungere il codice frammento di voi nel mio codice (potete trovare qui stackoverflow.com/questions/3667442/how-to-refresh-adapter ) in onCreate-metodo, ma io ancora non hanno alcun successo :( Forse è stato il posto sbagliato per aggiungerlo ?!
Tima

1
La tua domanda ti ha appena chiesto come potresti chiamare il metodo e farlo funzionare nel thread dell'interfaccia utente principale. Questo risponde a questa domanda. Nel vostro caso particolare ( stackoverflow.com/questions/3670500/... ) AsyncTask e il suo metodo () OnPostExecute sembrano essere ciò che si dovrebbe prendere in considerazione.
Brian,

12

Di recente ho scritto su questo argomento, anche se questo post è vecchio, ho pensato che sarebbe stato utile a qualcuno che volesse sapere come implementarlo BaseAdapter.notifyDataSetChanged()passo dopo passo e in modo corretto.

Segui Come implementare correttamente BaseAdapter.notifyDataSetChanged () in Android o il blog più recente BaseAdapter.notifyDataSetChanged () .


Ciao, ho provato il primo esempio di collegamento, ma invece di mItem.add()aver fatto solo la modifica di un elemento significa che mItem.get(position).setImage(encodedImage)potrebbe essere questo il motivo per cui sta dando errore NullPointer exeption. solo per add (), clear (), remove () ecc
Shreekant N

notifyDataSetChanged funzionerà per la modifica o la modifica del set di dati, il puntatore null è a causa di qualcos'altro, controlla i log.
Arif Nadeem,

7

Ho avuto lo stesso problema e preferisco non sostituire l'intero ArrayAdapter con una nuova istanza continuamente. Quindi ho AdapterHelper fare il sollevamento pesante altrove.

Aggiungi questo dove normalmente (provi a) chiamare la notifica

new AdapterHelper().update((ArrayAdapter)adapter, new ArrayList<Object>(yourArrayList));
adapter.notifyDataSetChanged();

Classe AdapterHelper

public class AdapterHelper {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public void update(ArrayAdapter arrayAdapter, ArrayList<Object> listOfObject){
        arrayAdapter.clear();
        for (Object object : listOfObject){
            arrayAdapter.add(object);
        }
    }
}

Ho un altro paio di ArrayAdapters nel mio codice e hanno funzionato senza problemi. Stasera, ho deciso di trasformare un SimpleCursorAdapter in un ArrayAdapter e NON FUNZIONA. Dopo aver lottato per qualche ora e aver cercato di trovare un motivo per cui non avrebbe funzionato, ho trovato la tua classe AdapterHelper e ADESSO FUNZIONA! Grazie!
proudgeekdad,

1
Questo può essere fatto facilmente in una funzione ... PERCHÉ vuoi creare un'istanza per una nuova classe?
techiServices

2
In Java le funzioni sono chiamate metodi. Cosa vorresti proporre, forse questo metodo altamente riutilizzabile nella stessa classe dell'adattatore di array forse? O il frammento / attività contenente la vista elenco? Quindi sì, è in una classe in cui può essere riutilizzato. Se vuoi renderlo statico, vai avanti.
Kevin Parker,

1
Bella idea Un altro sarebbe estendere ArrayAdapter, chiamato ArrayAdapterCompat e sovrascrivere il metodo addAll (..), poiché questo è disponibile solo dall'API 11. In là, controlla il livello API e usa super.addAll(..)API> 11 e super.add (.. ) in combinazione con l'iterazione come la tua: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { super.addAll(items); } else { for (Object o : collection) { super.add(o); } }. Ora estendi la tua nuova classe di adattatori.
Konsumierer,

Perfetto! Grazie mille @Kevin - questo era ESATTAMENTE quello di cui avevo bisogno!
Kibi,

3

So che questa è una risposta tardiva, ma stavo affrontando un problema simile e sono riuscito a risolverlo utilizzando notifyDataSetChanged() nel posto giusto.

Quindi la mia situazione era la seguente.

Ho dovuto aggiornare una visualizzazione elenco in una scheda della barra delle azioni (frammento) con i contenuti restituiti da un'attività completamente diversa. Inizialmente, tuttavia, la visualizzazione elenco non rifletterebbe alcun cambiamento. Tuttavia, quando ho fatto clic su un'altra scheda e poi sono tornato alla scheda desiderata, la visualizzazione elenco sarebbe stata aggiornata con il contenuto corretto dall'altra attività. Quindi per risolvere questo ho usatonotifyDataSetChanged() l'adattatore della barra delle azioni nel codice dell'attività che ha dovuto restituire i dati.

Questo è lo snippet di codice che ho usato nell'attività.

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) 
    {
        case R.id.action_new_forward:

            FragmentTab2.mListAdapter.notifyDataSetChanged();//this updates the adapter in my action bar tab
            Intent ina = new Intent(getApplicationContext(), MainActivity.class);
            ina.putExtra("stra", values1);
            startActivity(ina);// This is the code to start the parent activity of my action bar tab(fragment).
    }
}

Questa attività restituirebbe alcuni dati FragmentTab2e aggiornerebbe direttamente la mia visualizzazione elenco in FragmentTab2.

Spero che qualcuno lo trovi utile!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.