Exemple de notifyDataSetChanged

166

Je suis en train d'utiliser dans mon Android Applicationla notifyDataSetChanged()méthode pour un , ArrayAdaptermais il ne fonctionne pas pour moi.

J'ai trouvé comme réponse ici , qui notifyDataSetChanged()devrait fonctionner dans le fil principal, mais il n'y avait pas d'exemple pour cela.

Quelqu'un pourrait-il envoyer un exemple ou au moins un lien?!

Tima
la source
vous pouvez consulter ce blog et cet exemple dans github et ceci aussi
Cabezas

Réponses:

328

Pour un ArrayAdapter, notifyDataSetChangedne fonctionne que si vous utilisez add(), insert(), remove()et clear()sur l'adaptateur.

Quand un ArrayAdapterest construit, il contient la référence pour le Listqui a été transmis. Si vous deviez transmettre un Listqui était un membre d'une activité et changer ce membre d'activité ultérieurement, le contient ArrayAdaptertoujours une référence à l'original List. L'adaptateur ne sait pas que vous avez modifié le Listdans l'activité.

Vos choix sont:

  1. Utilisez les fonctions de ArrayAdaptermodifier la liste sous - jacente ( add(), insert(), remove(), clear(), etc.)
  2. Recréez le ArrayAdapteravec les nouvelles Listdonnées. (Utilise beaucoup de ressources et de garbage collection.)
  3. Créez votre propre classe dérivée de BaseAdapteret ListAdapterqui permet de modifier la Liststructure de données sous-jacente .
  4. Utilisez le notifyDataSetChanged()chaque fois que la liste est mise à jour. Pour l'appeler sur UI-Thread, utilisez le runOnUiThread()of Activity. Ensuite, notifyDataSetChanged()fonctionnera.
jnosek
la source
13
faites également attention d'attribuer de «nouveaux» objets à vos données. utilisez plutôt clear (), remplissez / modifiez les données, puis appelez notifyDataSetChanged ()
moonlightcheese
Mais que se passe-t-il si nous appelons notifyDataSetChanged()de cette manière ((BaseAdapter) arrayAdapter).notifyDataSetChanged();:?
teoREtik
2
J'utilise BaseExpandableListAdapter, il n'a pas de fonctions add () ou remove () donc je stocke ma carte en tant que variable membre. Je mets à jour Map et j'appelle notifyDatasetChanged () mais rien ne se passe. Quand j'utilise le choix n ° 4, cela fonctionne. Pourquoi???
emeraldhieu
J'utilise ArrayAdapter pour GridView personnalisé, j'ajoute des images au fur et à mesure que je les récupère à partir d'urls en appelant adapter.add (dataReceived). Cela fonctionne bien ajoute des données, mais pourquoi c'est rafraîchissant et aller en haut. Je veux afficher les éléments car ils seront ajoutés sans actualiser la liste. (Ce que vous voulez faire est de travailler avec GridView d'Android à l'aide de notifyDatasetChanged ()) Comment puis-je le faire fonctionner dans ce customGridView (StaggeredGridView).
MobileEvangelist
1
J'ai essayé de créer mon propre BaseAdapter pour ajouter des méthodes de tri à la liste, mais pour une raison quelconque, cela ne fonctionnait tout simplement pas. Non pas que mon application soit lente même si je recrée l'intégralité de l'adaptateur avec une liste triée, mais cela me dérange toujours. Mais comment créerait-il exactement beaucoup de déchets? Je suppose que le tableau réel de données coûteuses est conservé comme référence dans l'activité appelant l'adaptateur, ce qui signifie que seul l'adaptateur sera collecté.
G_V
34

Vous pouvez utiliser la runOnUiThread()méthode comme suit. Si vous n'utilisez pas a ListActivity, adaptez simplement le code pour obtenir une référence à votre ArrayAdapter.

final ArrayAdapter adapter = ((ArrayAdapter)getListAdapter());
runOnUiThread(new Runnable() {
    public void run() {
        adapter.notifyDataSetChanged();
    }
});
Brian
la source
1
J'ai essayé d'ajouter le fragment de code de vous dans mon code (vous pouvez le trouver ici stackoverflow.com/questions/3667442/how-to-refresh-adapter ) dans onCreate-method, mais je n'ai toujours pas de succès :( Peut-être que ce n'était pas le bon endroit pour l'ajouter?!
Tima
1
Votre question demandait simplement comment appeler la méthode et la faire exécuter dans le thread principal de l'interface utilisateur. Cela répond à cette question. Dans votre cas particulier ( stackoverflow.com/questions/3670500/… ) AsyncTask et sa méthode onPostExecute () semblent être ce que vous devriez considérer.
Brian
12

J'ai récemment écrit sur ce sujet, bien que ce post soit vieux, j'ai pensé qu'il serait utile à quelqu'un qui veut savoir comment mettre en œuvre BaseAdapter.notifyDataSetChanged()étape par étape et de manière correcte.

Veuillez suivre Comment implémenter correctement BaseAdapter.notifyDataSetChanged () dans Android ou le blog plus récent BaseAdapter.notifyDataSetChanged () .

Arif Nadeem
la source
Salut, j'ai essayé le premier exemple de lien, mais au lieu de mItem.add(), je n'ai fait que modifier un élément signifie que c'est mItem.get(position).setImage(encodedImage)peut-être pour cela qu'il donne une erreur NullPointer exeption.Alors, notifyDataSetChange fonctionne simplement en le modifiant, bcz pour l'adaptateur Array, il est mentionné ci-dessus, cela fonctionne uniquement pour add (), clear (), remove () etc
Shreekant N
notifyDataSetChanged fonctionnera pour éditer ou modifier l'ensemble de données, votre pointeur nul est dû à autre chose, vérifiez les journaux.
Arif Nadeem
7

J'ai eu le même problème et je préfère ne pas remplacer l'ensemble de l'ArrayAdapter par une nouvelle instance en continu. Ainsi, je demande à AdapterHelper de faire le gros du travail ailleurs.

Ajoutez ceci là où vous appelleriez normalement (essayez d'appeler) notifier

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);
        }
    }
}
Kevin Parker
la source
J'ai quelques autres ArrayAdapters dans mon code et ils ont fonctionné sans problème. Ce soir, j'ai décidé de transformer un SimpleCursorAdapter en un ArrayAdapter, et cela NE FONCTIONNE PAS. Après avoir lutté avec lui pendant quelques heures et essayé de trouver une raison pour laquelle cela ne fonctionnerait pas, j'ai trouvé votre classe AdapterHelper, et MAINTENANT CELA FONCTIONNE! Merci!
proudgeekdad
1
Cela peut facilement être fait dans une fonction ... POURQUOI voudriez-vous instancier une nouvelle classe pour elle?
techiServices
2
En Java, les fonctions sont appelées méthodes. Que proposeriez-vous, avoir cette méthode hautement réutilisable dans la même classe que l'adaptateur Array? Ou le fragment / activité contenant la vue de liste? Alors oui, c'est dans une classe où il peut être réutilisé. Si vous voulez le rendre statique par tous les moyens, allez-y.
Kevin Parker
1
Bonne idée. Un autre serait d'étendre ArrayAdapter, nommé ArrayAdapterCompat et de remplacer la méthode addAll (..), car celle-ci n'est disponible que depuis l'API 11. Là, vérifiez le niveau d'API et utilisez super.addAll(..)pour API> 11 et super.add (.. ) en combinaison avec itération comme le vôtre: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { super.addAll(items); } else { for (Object o : collection) { super.add(o); } }. Maintenant, étendez simplement votre nouvelle classe d'adaptateur.
Konsumierer
Parfait! Merci beaucoup @Kevin - c'était EXACTEMENT ce dont j'avais besoin!
Kibi le
3

Je sais que c'est une réponse tardive, mais j'étais confronté à un problème similaire et j'ai réussi à le résoudre en utilisant notifyDataSetChanged()au bon endroit.

Ma situation était donc la suivante.

J'ai dû mettre à jour une liste dans un onglet de la barre d'action (fragment) avec le contenu renvoyé par une activité complètement différente. Cependant, au départ, la vue de liste ne refléterait aucun changement. Cependant, lorsque je cliquais sur un autre onglet, puis retournais à l'onglet souhaité, la liste était mise à jour avec le contenu correct de l'autre activité. Donc, pour résoudre ce problème, j'ai utilisé notifyDataSetChanged()l'adaptateur de barre d'action dans le code de l'activité qui devait renvoyer les données.

Voici l'extrait de code que j'ai utilisé dans l'activité.

@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).
    }
}

Cette activité renverrait des données à FragmentTab2et mettrait directement à jour ma liste dans FragmentTab2.

J'espère que quelqu'un trouvera cela utile!

mutp
la source