Ejemplo de notifyDataSetChanged

166

Estoy tratando de utilizar en mi Android Applicationel notifyDataSetChanged()método para una ArrayAdapterpero no funciona para mí.

Encontré como respuesta aquí , que notifyDataSetChanged()debería ejecutarse en el hilo principal, pero no había ningún ejemplo para eso.

¿Alguien podría enviar un ejemplo o al menos un enlace?

Tima
fuente
puedes consultar este blog y este ejemplo en github y esto también
Cabezas

Respuestas:

328

Para una ArrayAdapter, notifyDataSetChangedsólo funciona si se utiliza el add(), insert(), remove(), y clear()en el adaptador.

Cuando ArrayAdapterse construye un, contiene la referencia para lo Listque se pasó. Si fuera a pasar Listun miembro de una Actividad, y cambiara ese miembro de la Actividad más adelante, el ArrayAdaptertodavía tiene una referencia al original List. El adaptador no sabe que ha cambiado el Listen la actividad.

Sus elecciones son:

  1. Utilice las funciones de la ArrayAdapterde modificar la Lista subyacente ( add(), insert(), remove(), clear(), etc.)
  2. Vuelva a crear el ArrayAdaptercon los nuevos Listdatos. (Utiliza muchos recursos y recolección de basura).
  3. Cree su propia clase derivada BaseAdaptery ListAdapterque permita cambiar la Listestructura de datos subyacente .
  4. Use notifyDataSetChanged()cada vez que se actualice la lista. Para llamarlo en el UI-Thread, use el runOnUiThread()de Activity. Entonces, notifyDataSetChanged()funcionará.
jnosek
fuente
13
tenga cuidado también de asignar objetos 'nuevos' a sus datos. use clear () en su lugar, vuelva a llenar / realice cambios en los datos, luego llame a notifyDataSetChanged ()
moonlightcheese
Pero, ¿qué pasa si llamamos notifyDataSetChanged()de esa manera ((BaseAdapter) arrayAdapter).notifyDataSetChanged();:?
teoREtik
2
Uso BaseExpandableListAdapter, no tiene funciones add () o remove (), así que almaceno mi Mapa como una variable miembro. Actualizo Map y llamo notifyDatasetChanged () pero no sucede nada. Cuando uso la opción # 4, funciona. ¿¿¿Por qué???
emeraldhieu
Estoy usando ArrayAdapter para GridView personalizado, agrego imágenes a medida que las obtengo de las URL al llamar a adapter.add (dataReceived). Esto funciona bien agrega datos, pero por qué es refrescante y va al principio. Quiero mostrar elementos ya que se agregarán sin actualizar la lista. (Lo que quiero hacer es trabajar con GridView de Android usando notifyDatasetChanged ()) ¿Cómo puedo hacer que funcione en este customGridView (StaggeredGridView)?
MobileEvangelist
1
Intenté crear mi propio BaseAdapter para agregar métodos de clasificación a la lista, pero por alguna razón simplemente no funcionó. No es que mi aplicación sea lenta, incluso si recrea el adaptador completo con una lista de arrays ordenada, pero aún así me molesta. ¿Cómo exactamente crearía mucha basura? Supongo que la matriz real de datos costosos se mantiene como referencia en la actividad que llama al adaptador, lo que significa que solo se recopilará el adaptador.
G_V
34

Puede usar el runOnUiThread()método de la siguiente manera. Si no está utilizando un ListActivity, simplemente adapte el código para obtener una referencia a su ArrayAdapter.

final ArrayAdapter adapter = ((ArrayAdapter)getListAdapter());
runOnUiThread(new Runnable() {
    public void run() {
        adapter.notifyDataSetChanged();
    }
});
Brian
fuente
1
Traté de agregar el fragmento de código de usted en mi código (puede encontrarlo aquí stackoverflow.com/questions/3667442/how-to-refresh-adapter ) en onCreate-method, pero todavía no tengo ningún éxito :( Tal vez fue un lugar incorrecto para agregarlo ?!
Tima
1
Su pregunta solo pregunta cómo puede llamar al método y ejecutarlo en el hilo principal de la interfaz de usuario. Esto responde a esa pregunta. En su caso particular ( stackoverflow.com/questions/3670500/… ) AsyncTask y su método onPostExecute () parecen ser lo que debe considerar.
Brian
12

Recientemente escribí sobre este tema, aunque esta publicación es antigua, pensé que sería útil para alguien que quiera saber cómo implementar BaseAdapter.notifyDataSetChanged()paso a paso y de manera correcta.

Siga Cómo implementar correctamente BaseAdapter.notifyDataSetChanged () en Android o el blog más reciente BaseAdapter.notifyDataSetChanged () .

Arif Nadeem
fuente
Hola, probé el primer ejemplo de enlace, pero en lugar de mItem.add()hacerlo, solo edité un elemento, mItem.get(position).setImage(encodedImage)por lo que es posible que esté dando una excepción de error de puntero nulo. solo para add (), clear (), remove (), etc.
Shreekant N
notifyDataSetChanged funcionará para editar o modificar el conjunto de datos, su puntero nulo se debe a algo más, verifique los registros.
Arif Nadeem
7

Tuve el mismo problema y prefiero no reemplazar todo el ArrayAdapter con una nueva instancia continuamente. Por lo tanto, tengo el AdapterHelper haciendo el trabajo pesado en otro lugar.

Agregue esto donde normalmente (intente) llamar notificar

new AdapterHelper().update((ArrayAdapter)adapter, new ArrayList<Object>(yourArrayList));
adapter.notifyDataSetChanged();

Clase AdapterHelper

public class AdapterHelper {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public void update(ArrayAdapter arrayAdapter, ArrayList<Object> listOfObject){
        arrayAdapter.clear();
        for (Object object : listOfObject){
            arrayAdapter.add(object);
        }
    }
}
Kevin Parker
fuente
Tengo un par de otros ArrayAdapters en mi código y han funcionado sin problemas. Esta noche, decidí convertir un Adaptador de cursor simple en un Adaptador de matriz, y NO FUNCIONARÍA. Después de luchar con él durante unas horas e intentar encontrar una razón por la que no funcionaría, encontré su clase AdapterHelper, ¡y AHORA FUNCIONA! ¡Gracias!
proudgeekdad
1
Esto se puede hacer fácilmente en una función ... ¿POR QUÉ crearías una nueva clase para ella?
techiServices
2
En Java las funciones se denominan métodos. ¿Qué propondría, tener este método altamente reutilizable en la misma clase que el adaptador de matriz, tal vez? ¿O el Fragmento / Actividad que contiene la vista de lista? Entonces sí, está en una clase donde se puede reutilizar. Si quieres que sea estático por todos los medios, adelante.
Kevin Parker el
1
Buena idea. Otro sería extender ArrayAdapter, llamado ArrayAdapterCompat y anular el método addAll (..), ya que este solo está disponible desde la API 11. Allí, verifique el nivel de API y use super.addAll(..)para API> 11 y super.add (.. ) en combinación con la iteración como la suya: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { super.addAll(items); } else { for (Object o : collection) { super.add(o); } }. Ahora solo extiéndase de su nueva clase de adaptador.
Konsumierer
¡Perfecto! Muchas gracias @Kevin, ¡esto era EXACTAMENTE lo que necesitaba!
Kibi
3

Sé que esta es una respuesta tardía, pero estaba enfrentando un problema similar y logré resolverlo usando notifyDataSetChanged()en el lugar correcto.

Entonces mi situación fue la siguiente.

Tuve que actualizar una vista de lista en una pestaña de barra de acción (fragmento) con contenido devuelto de una actividad completamente diferente. Inicialmente, sin embargo, la vista de lista no reflejaría ningún cambio. Sin embargo, cuando hice clic en otra pestaña y luego volví a la pestaña deseada, la vista de lista se actualizaría con el contenido correcto de la otra actividad. Entonces para resolver esto usénotifyDataSetChanged() el adaptador de barra de acción en el código de la actividad que tenía que devolver los datos.

Este es el fragmento de código que utilicé en la actividad.

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) 
    {
        case R.id.action_new_forward:

            FragmentTab2.mListAdapter.notifyDataSetChanged();//this updates the adapter in my action bar tab
            Intent ina = new Intent(getApplicationContext(), MainActivity.class);
            ina.putExtra("stra", values1);
            startActivity(ina);// This is the code to start the parent activity of my action bar tab(fragment).
    }
}

Esta actividad devolvería algunos datos FragmentTab2y actualizaría directamente mi vista de lista en FragmentTab2.

¡Espero que alguien encuentre esto útil!

mutp
fuente