web-dev-qa-db-fra.com

Android: notifyDataSetChanged (); Ca ne fonctionne pas

J'ai une base de données sur un serveur et à partir d'une tablette, je prends certaines valeurs d'une table de la base de données. Je charge correctement ces informations dans une liste mais je voudrais savoir pourquoi quand il y a un changement, rien ne se passe même si j'utilise notifyDataSetChanged();. Je dois dire que pour charger les données de chargement, utilisez le AsyncTaskClass Donc, mon problème est que je ne sais pas si j'utilise le notifyDataSetChanged (); correctement, car s'il y a un changement, je voudrais rafraîchir l'image. Voici une partie du code de la classe:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.all_candidatos);


        candidatosList = new ArrayList<HashMap<String, String>>();

        new CargarCandidatos().execute();
    }


//  public void timer(){
//       new CountDownTimer(tiempo, 100) {
//
//              public void onTick(long millisUntilFinished) {
//                  
//              }
//
//              public void onFinish() {
//              //  new CargarCandidatos().execute();
//
//              }
//           }.start();}



    /**
     * Background Async Task to Load all product by making HTTP Request
     * */
    class CargarCandidatos extends AsyncTask<String, String, String> {

        /**
         * Before starting background thread Show Progress Dialog
         * */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(Monitorizacion.this);
            pDialog.setMessage("Loading ...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(false);
            pDialog.show();
        }

        /**
         * getting All products from url
         * */
        protected String doInBackground(String... args) {
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            JSONObject json = jParser.makeHttpRequest(url_candidatos, "GET", params);

            Log.d("Candidatos: ", json.toString());

            try {
                int success = json.getInt(TAG_SUCCESS);

                if (success == 1) {

                    candidatos = json.getJSONArray(TAG_CANDIDATOS);

                    for (int i = 0; i < candidatos.length(); i++) {
                        JSONObject c = candidatos.getJSONObject(i);

                        // Storing each json item in variable
                        String nserie = c.getString(TAG_NSERIE);
                        String dni = c.getString(TAG_DNI);
                        String nombre = c.getString(TAG_NOMBRE);
                        String test = c.getString(TAG_TEST);
                        String pregunta = c.getString(TAG_PREGUNTA);
                        String bateria = c.getString(TAG_BATERIA);

                        // creating new HashMap
                        HashMap<String, String> map = new HashMap<String, String>();

                        // adding each child node to HashMap key => value
                        map.put(TAG_NSERIE, nserie);
                        map.put(TAG_DNI, dni);
                        map.put(TAG_NOMBRE, nombre);
                        map.put(TAG_TEST, test);
                        map.put(TAG_PREGUNTA, pregunta);
                        map.put(TAG_BATERIA, bateria);

                        // adding HashList to ArrayList
                        candidatosList.add(map);
                    }
                } 
            } catch (JSONException e) {
                e.printStackTrace();
            }

            return null;
        }

        /**
         * After completing background task Dismiss the progress dialog
         * **/
        protected void onPostExecute(String file_url) {
            pDialog.dismiss();
            runOnUiThread(new Runnable() {
                public void run() {
                    /**
                     * Updating parsed JSON data into ListView
                     * */
                    adapter = new SimpleAdapter(
                            Monitorizacion.this, candidatosList,
                            R.layout.list_item, new String[] { TAG_NSERIE,
                                    TAG_DNI, TAG_NOMBRE, TAG_TEST, TAG_PREGUNTA, TAG_BATERIA},
                            new int[] { R.id.id, R.id.dni, R.id.nombre, R.id.test, R.id.pregunta, R.id.bateria});
                    setListAdapter(adapter);
                    adapter.notifyDataSetChanged();
                //  timer();
                }
            });

        }

    }
}
19
Katherine99

L'une des principales raisons pour lesquelles notifyDataSetChanged() ne fonctionnera pas pour vous - est,

Votre adaptateur perd la référence à votre liste.

Lorsque vous initialisez pour la première fois le Adapter, il prend une référence de votre arrayList et le transmet à sa superclasse. Mais si vous réinitialisez votre arrayList existant, il perd la référence, et donc le canal de communication avec Adapter.

Lors de la création et de l'ajout d'une nouvelle liste au Adapter. Suivez toujours ces directives:

  1. Initialisez le arrayList tout en le déclarant globalement.
  2. Ajoutez la liste à l'adaptateur directement sans vérifier les valeurs nulles et vides. Réglez directement l'adaptateur sur la liste (ne recherchez aucune condition). L'adaptateur vous garantit que partout où vous apporterez des modifications aux données du arrayList, il s'en occupera, mais ne perdra jamais la référence.
  3. Modifiez toujours les données dans la arrayList elle-même (si vos données sont complètement nouvelles, vous pouvez appeler adapter.clear() et arrayList.clear() avant d'ajouter réellement des données à la liste) mais ne définissez pas l'adaptateur ie Si les nouvelles données sont remplies dans le arrayList que simplement adapter.notifyDataSetChanged()

Restez fidèle à la documentation.

95

La chose que vous devez modifier est de mettre votre

runOnUiThread(new Runnable() {
                public void run() {
                    /**
                     * Updating parsed JSON data into ListView
                     * */
                    adapter = new SimpleAdapter(
                            Monitorizacion.this, candidatosList,
                            R.layout.list_item, new String[] { TAG_NSERIE,
                                    TAG_DNI, TAG_NOMBRE, TAG_TEST, TAG_PREGUNTA, TAG_BATERIA},
                            new int[] { R.id.id, R.id.dni, R.id.nombre, R.id.test, R.id.pregunta, R.id.bateria});
                    setListAdapter(adapter);
                    adapter.notifyDataSetChanged();
                //  timer();
                }
            });

dans OnCreate (). et renvoyez la liste candidatosList d'Asynctask. que de régler la minuterie pour la mise à jour de la liste candidatosList.

5
user1621629

Il peut être utile de vérifier si vous avez un remplacement vide pour registerDataSetObserver(). Android Studio en a ajouté un pour moi sans implémenter l'appel à super. L'ajouter comme suit était suffisant pour que ma listView fonctionne à nouveau:

@Override
    public void registerDataSetObserver(DataSetObserver observer) {
        super.registerDataSetObserver(observer);    
    }
4
head in the codes

Un adaptateur définit le comportement de la mise en page! -> setListAdapter (): Définissez l'adaptateur pour un ListView/GridView/Gallery ... mais vous devez spécifier les données!

Je vous recommande d'initialiser 'setListAdapter' dans 'onCreate' ou dans le constructeur. Après avoir défini les données dans l'adaptateur (exemple: adapter.setItem (yourData))

Et maintenant ! Vous devez appeler notifyDataSetChanged! Parce que vous avez modifié les données mais la vue n'est pas actualisée et notifydatasetchanged () recharge le contenu de la vue (ListView/GridView/Gallery ... )

Pour une bonne pratique et bien comprendre, je vous recommande d'utiliser un 'adaptateur personnalisé' en utilisant ' baseAdapter '

Lisez et faites ce tutoriel (j'ai appris avec cela): http://www.androidhive.info/2012/02/02/Android-custom-listview-with-image-and-text/

Lisez la documentation: http://developer.Android.com/reference/Android/widget/BaseAdapter.html

3
VincentLamoute

La fonction de mise à jour doit être appelée à partir du thread d'interface utilisateur. Ma réponse est en fait similaire à celle de @ user1621629 answer avec cette différence que j'utilise rxJava, alors voici le code de travail qui résout ce problème pour moi:

this.subscriber = myAdapter.getSubscriber(); // keep for unsubscribe in destroy
dataSource.subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread()).subscribe(this.subscriber);

J'ai donc défini toutes les exécutions afin d'obtenir des données pour la liste sur le thread de calcul, mais montrant le résultat dans le thread d'interface utilisateur.

Voici comment je crée un abonné pour cela:

public class MyListAdapter extends RecyclerView.Adapter<LocationListAdapter.ViewHolder> {


private List<ListItem> mDataset = new ArrayList<>();

public Subscriber<ListItem[]> getSubscriber() {
    return Subscribers.create(new Action1<ListItem[]>() {
        @Override
        public void call(ListItem[] listItems) {
            mDataset.clear();
            mDataset.addAll(Arrays.asList(listItems));
            notifyDataSetChanged();
        }
    });
}
......
2
msangel

Comme Hissain décrit ci-dessus ,

vous devez conserver une référence à la liste

Voici comment je l'ai fait fonctionner:

  1. Laissez la liste envoyée à l'adaptateur être définie en tant que membre d'instance dans l'activité

  2. Dans la logique qui effectue une modification des données, assurez-vous qu'elle met à jour la même instance de liste que l'activité transmise à l'adaptateur

  3. Appelant ensuite .notifyDataSetChanged (); travaillé

N'oubliez pas que la position listView commence à 1, vous devrez donc faire (listViewPosition - 1) pour votre Java.util.List

1
Gene Bo

Je n'ai pas beaucoup de réputation pour commenter la réponse de M. Hissain. C'est correct mais je veux mentionner une chose de plus que la référence à la liste ne devrait pas changer. Si la source de données sous-jacente change, ne modifiez pas la référence à la nouvelle liste. Les actions doivent uniquement être effectuées sur le même objet de liste. Pour faire de même, effacez la liste à l'aide de clear (), puis ajoutez des données à la même liste à l'aide de add () ou addALL (), puis appelez notifyDataSetChanged (). par exemple. Lors de la première initialisation de la liste

list = dataSource.getList();

alors on peut ajouter et supprimer le contenu de la liste et appeler notifyDataSetChanged () ça marche bien mais si dans le code, on essaie de changer la référence à l'autre objet. Comme

list = dataSource.getList();

où getList () renvoie la nouvelle liste à chaque fois, donc la référence change à un autre objet de liste et l'appel à notifyDataSetChnaged n'a pas d'impact sur la liste.Mais si getList () renvoie le même objet de liste, cela fonctionne très bien.

0
Raghav Sharma