update recyclerview from activity android refresh adapter

android - from - refresh recyclerview adapter



Android: notifyDataSetChanged(); no funciona (7)

Tengo una base de datos en un servidor y desde una tableta tomo algunos valores de una tabla en la base de datos. Cargo esta información correctamente en una lista, pero me gustaría saber por qué cuando hay un cambio, no pasa nada, incluso si uso notifyDataSetChanged(); . Debo decir que para cargar los datos de carga y uso la clase AsyncTaskClass, mi problema es que no sé si utilizar la notificación 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<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(); } }); } } }


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 actualizar la misma instancia de lista que la actividad pasó al adaptador

  3. Luego llamando 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 ser llamada desde el hilo de la interfaz de usuario. En realidad, mi respuesta es similar a la answer @ 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 configuro toda la ejecución para obtener datos de la lista en el hilo de cálculo, pero mostrando el resultado en el hilo de la interfaz de usuario.

Así es como creo suscriptor para esto:

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


Lo que necesitas editar es poner tu

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 de candidatosList desde Asynctask. que el temporizador establecido para actualizar la lista de candidatos.


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 debe cambiar. Si la fuente de datos subyacente está cambiando, no cambie la referencia a una 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 los 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();

luego uno puede agregar y eliminar el contenido de la lista y llamar a NotifyDataSetChanged () funciona bien, pero si en el código, uno intenta 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 lista y llamar a notificationDataSetChnaged no tiene impacto en la lista. Pero si getList () devuelve el mismo objeto de lista, funciona bien.


Podría valer la pena comprobar si tiene un reemplazo vacío para registerDataSetObserver() . Android Studio agregó uno para mí 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); }


Un adaptador define el comportamiento del layout! -> 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 (por ejemplo: adapter.setItem (yourData))

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

Para una buena práctica y para entenderlo correctamente, le recomiendo que use un ''adaptador personalizado'' con '' baseAdapter ''

Lea y haga este tutorial (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


Una de las razones principales por las que notifyDataSetChanged() no funciona para usted es que

Su adaptador pierde la referencia a su lista .

Cuando inicializa el Adapter primera vez, toma una referencia de su arrayList y lo pasa a su superclase. Pero si reinicializa su 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. Establezca el adaptador en la lista directamente (no verifique ninguna condición). Adapter le garantiza que siempre que realice cambios en los datos de la arrayList se encargará de ello, pero nunca perderá la referencia.
  3. Siempre modifique los datos en la propia arrayList (si sus datos son completamente nuevos de lo que puede llamar a adapter.clear() y arrayList.clear() antes de agregar datos a la lista) pero no configure el adaptador, es decir, si los nuevos datos se llena en la arrayList de arrayList que solo adapter.notifyDataSetChanged()

Mantenerse fiel a la documentación.