Android: notifyDataSetChanged(); not working

夙愿已清 提交于 2019-11-26 08:24:40

问题


I have a database in a server and from a Tablet I take some values from one table in the database. I load this information correctly into a list but I would like to know why when there is a change, nothing happens even if I use notifyDataSetChanged();. I must say that for loading the loading data y use the AsyncTaskClass So, my problem is that I don\'t know if use the notifyDataSetChanged(); method correctly ,because if there\'s is a change I would like to refresh the image. Here is some part of the code of the class:

@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();
                }
            });

        }

    }
}

回答1:


One of the main reasons notifyDataSetChanged() won't work for you - is,

Your adapter loses reference to your list.

When you first initialise the Adapter it takes a reference of your arrayList and passes it to its superclass. But if you reinitialise your existing arrayList it losses the reference, and hence, the communication channel with Adapter.

When creating and adding a new list to the Adapter. Always follow these guidelines:

  1. Initialise the arrayList while declaring it globally.
  2. Add the List to the adapter directly with out checking for null and empty values . Set the adapter to the list directly (don't check for any condition). Adapter guarantees you that wherever you make changes to the data of the arrayList it will take care of it, but never loose the reference.
  3. Always modify the data in the arrayList itself (if your data is completely new than you can call adapter.clear() and arrayList.clear() before actually adding data to the list) but don't set the adapter i.e If the new data is populated in the arrayList than just adapter.notifyDataSetChanged()

Stay true to the Documentation.




回答2:


The thing you need to edit is put your

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();
                }
            });

into the OnCreate(). and return the list candidatosList from Asynctask. than set timer for updating candidatosList list.




回答3:


It might be worth checking if you have an empty override for registerDataSetObserver(). Android Studio added one for me without implementing the call to super. Adding it in as follows was enough to get my listView working again:

@Override
    public void registerDataSetObserver(DataSetObserver observer) {
        super.registerDataSetObserver(observer);    
    }



回答4:


An adapter define the comportement of the layout ! -> setListAdapter() : Define the adapter for a ListView/GridView/Gallery... but you need to specify the data !

I recommend to you, to initialize 'setListAdapter' in the 'onCreate' or in the constructor. After you set the data into the adapter (exemple : adapter.setItem(yourData))

And NOW ! You should to call notifyDataSetChanged ! Because you have changed the data but the view isn't refresh and notifydatasetchanged() reload the content of the view (ListView/GridView/Gallery...)

For a good practice and understand correctly I recommend to you to use a 'custom adapter' using 'baseAdapter'

Read and do this tutorial (I haver learn with this): http://www.androidhive.info/2012/02/android-custom-listview-with-image-and-text/

Read the documentation : http://developer.android.com/reference/android/widget/BaseAdapter.html




回答5:


The update function should be called from UI thread. My answer is actually similar to @user1621629's answer with that difference that I am using rxJava, so here's working code that solve this problem for me:

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

So I set all execution in order to get data for the list to computation thread, but showing result in UI thread.

Here's how I create subscriber for this:

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();
        }
    });
}
......



回答6:


As Hissain describes above,

you need to maintain a reference to the list

Here's how I got it to work:

  1. Let the list being sent to the adapter be set as an instance member in the activity

  2. In the logic that performs a change to the data, make sure it updates the same list instance that the activity passed to the adapter

  3. Then calling .notifyDataSetChanged(); worked

Remember that listView position starts at 1, so you will have to do (listViewPosition - 1) for your your java.util.List




回答7:


I dont have much reputation to comment on Mr. Hissain answer.It is correct but I want to mention one more thing that reference to the list should not change. If data source underlying is changing, dont change the reference to new list. Actions only need to be done on the same list object. To do the same,clear the list using clear() and then add data to the same list using add() or addALL() and then call notifyDataSetChanged(). eg. On first initialization of the list

list = dataSource.getList();

then one can add and remove the content from the list and call notifyDataSetChanged() it works fine but if in the code, one tries to change the reference to the other object. Like

list = dataSource.getList();

where getList() returns the new list everytime, hence the reference changes to some other list object and calling notifyDataSetChnaged does not have impact on the list.But if getList() returns the same list object, it works fine.




回答8:


If everything you set fine and still not working then your list... Is it Mutablekind of the List or not...!

private val demoList: MutableList<AnyClass> = mutableListOf()

once you define your list like above mutable manner then you can get the method

.add
.addAll
.remove

etc...

else if you have created normal list then that will not work as notifyDataSetChanged



来源:https://stackoverflow.com/questions/16165728/android-notifydatasetchanged-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!