Android: notifyDataSetChanged (); no funciona

Tengo una base de datos en un servidor y desde una tableta tomo algunos valores de una tabla en la base de datos. Cargué esta información correctamente en una lista, pero me gustaría saber por qué cuando hay un cambio, no ocurre nada incluso si uso notifyDataSetChanged(); . Debo decir que para cargar los datos de carga y usar AsyncTaskClass, mi problema es que no sé si usar notifyDataSetChanged (); método correctamente, porque si hay un cambio me gustaría actualizar la imagen. Aquí hay una parte del código de la clase:

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.all_candidatos); candidatosList = new ArrayList<HashMap>(); 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 { /** * 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 params = new ArrayList(); 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 map = new HashMap(); // 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(); } }); } } } 

Una de las razones principales por las que notifyDataSetChanged() no funcionará para usted, es decir,

Su adaptador pierde referencia a su lista .

Cuando inicializa el Adapter primera vez, toma una referencia de su arrayList y lo pasa a su superclase. Pero si reinicia su lista de arrayList existente, arrayList la referencia y, por lo tanto, el canal de comunicación con el Adapter .

Al crear y agregar una nueva lista al Adapter . Siempre siga estas pautas:

  1. Inicialice el arrayList mientras lo declara globalmente.
  2. Agregue la lista al adaptador directamente sin verificar los valores nulos y vacíos. Configure el adaptador directamente en la lista (no verifique ninguna condición). El adaptador le garantiza que siempre que realice cambios en los datos de la lista de arrayList , se encargará de ello, pero nunca perderá la referencia.
  3. Siempre modifique los datos en el arrayList mismo (si sus datos son completamente nuevos, puede llamar a adapter.clear() y arrayList.clear() antes de agregar datos a la lista) pero no configure el adaptador, es decir, si los datos nuevos está poblado en la arrayList de arrayList que simplemente adapter.notifyDataSetChanged()

Mantente fiel a la Documentación.

Lo que necesita para editar es poner su

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

en el OnCreate (). y devuelve la lista filaList desde Asynctask. que configurar el temporizador para actualizar la lista de lista de candidatos.

¡Un adaptador define el comportement del diseño! -> setListAdapter (): defina el adaptador para un ListView / GridView / Gallery … ¡pero necesita especificar los datos!

Te recomiendo, para inicializar ‘setListAdapter’ en ‘onCreate’ o en el constructor. Después de configurar los datos en el adaptador (ejemplo: adapter.setItem (yourData))

Y ahora ! ¡Deberías llamar a notifyDataSetChanged! Debido a que ha cambiado los datos, pero la vista no se actualiza y notifica que se han cambiado los datos (), vuelva a cargar el contenido de la vista (ListView / GridView / Gallery …)

Para una buena práctica y entender correctamente te recomiendo usar un ‘adaptador personalizado’ usando ‘ baseAdapter

Lea y haga este tutorial (ya he aprendido con esto): http://www.androidhive.info/2012/02/android-custom-listview-with-image-and-text/

Lea la documentación: http://developer.android.com/reference/android/widget/BaseAdapter.html

Vale la pena verificar si tiene una anulación vacía para registerDataSetObserver() . Android Studio me agregó uno sin implementar la llamada a super. Agregarlo de la siguiente manera fue suficiente para que mi ListView vuelva a funcionar:

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

Como Hissain describe arriba ,

necesitas mantener una referencia a la lista

Así es como lo hice funcionar:

  1. Deje que la lista que se envía al adaptador se establezca como un miembro de instancia en la actividad

  2. En la lógica que realiza un cambio en los datos, asegúrese de que actualiza la misma instancia de lista que la actividad pasó al adaptador

  3. Luego, se llama a .notifyDataSetChanged (); trabajó

Recuerde que la posición listView comienza en 1, por lo que tendrá que hacer (listViewPosition – 1) para su java.util.List

La función de actualización debe invocarse desde el hilo de UI. Mi respuesta es en realidad similar a la respuesta de @ user1621629 con la diferencia de que estoy usando rxJava, así que aquí está el código de trabajo que resuelve este problema para mí:

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

Así que configuré toda la ejecución para obtener datos de la lista para el hilo de cálculo, pero mostrando el resultado en el hilo de UI.

Así es como creo un suscriptor para esto:

 public class MyListAdapter extends RecyclerView.Adapter { private List mDataset = new ArrayList<>(); public Subscriber getSubscriber() { return Subscribers.create(new Action1() { @Override public void call(ListItem[] listItems) { mDataset.clear(); mDataset.addAll(Arrays.asList(listItems)); notifyDataSetChanged(); } }); } ...... 

No tengo mucha reputación para comentar sobre la respuesta del Sr. Hissain. Es correcto, pero quiero mencionar una cosa más que la referencia a la lista no debería cambiar. Si la fuente de datos subyacente está cambiando, no cambie la referencia a la nueva lista. Las acciones solo deben hacerse en el mismo objeto de lista. Para hacer lo mismo, borre la lista usando clear () y luego agregue datos a la misma lista usando add () o addALL () y luego llame a notifyDataSetChanged (). p.ej. En la primera inicialización de la lista

 list = dataSource.getList(); 

entonces uno puede agregar y eliminar el contenido de la lista y llamar a notifyDataSetChanged () funciona bien, pero si está en el código, uno trata de cambiar la referencia al otro objeto. Me gusta

 list = dataSource.getList(); 

donde getList () devuelve la nueva lista cada vez, por lo tanto la referencia cambia a algún otro objeto de la lista y llamar a notifyDataSetChnaged no tiene impacto en la lista. Pero si getList () devuelve el mismo objeto de la lista, funciona bien.