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:
Deje que la lista que se envía al adaptador se establezca como un miembro de instancia en la actividad
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
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:
- Inicialice el
arrayList
mientras lo declara globalmente. - 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. - Siempre modifique los datos en la propia arrayList (si sus datos son completamente nuevos de lo que puede llamar a
adapter.clear()
yarrayList.clear()
antes de agregar datos a la lista) pero no configure el adaptador, es decir, si los nuevos datos se llena en laarrayList
dearrayList
que soloadapter.notifyDataSetChanged()
Mantenerse fiel a la documentación.