2010-09-08 30 views
138

Estoy tratando de usar en mi Android Application el método notifyDataSetChanged() para un ArrayAdapter pero no funciona para mí.notifyDataSetChanged example

Encontré as answer here, 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?

+0

http://stackoverflow.com/questions/14503006/android-listview-not-refreshing-after-notifydatasetchanged – ranjan

Respuesta

294

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

Cuando se construye un ArrayAdapter, que contiene la referencia para el List que fue aprobada en. Si se va a pasar en un List que era un miembro de una actividad, y cambiar ese miembro Actividad más tarde, el ArrayAdapter aún se mantiene una referencia al original List. El adaptador no sabe que cambió el List en la actividad.

Las opciones son:

  1. utilizar las funciones de la ArrayAdapter para modificar la lista subyacente (add(), insert(), remove(), clear(), etc.)
  2. volver a crear el ArrayAdapter con los nuevos datos List . (Utiliza muchos recursos y recolección de basura.)
  3. Crea tu propia clase derivada de BaseAdapter y ListAdapter que permite el cambio de la estructura de datos subyacente List.
  4. Utilice notifyDataSetChanged() cada vez que se actualice la lista. Para llamarlo en el UI-Thread, use el runOnUiThread() de Activity. Luego, notifyDataSetChanged() funcionará.
+12

tenga cuidado, también, de asignar objetos 'nuevos' a sus datos. Utilice clear() en su lugar, repoblar/hacer cambios a los datos, luego invocar notifyDataSetChanged() – moonlightcheese

+0

Pero, ¿qué ocurre si llamamos a 'notifyDataSetChanged()' de tal manera: '((BaseAdapter) arrayAdapter) .notifyDataSetChanged();'? – teoREtik

+2

Utilizo BaseExpandableListAdapter, no tiene funciones add() o remove(), así que almaceno mi Map como una variable miembro. Actualizo Map y llamo notifyDatasetChanged() pero no ocurre nada. Cuando uso la opción # 4, funciona. ¿¿¿Por qué??? – Emerald214

28

Puede utilizar el método runOnUiThread() 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(); 
    } 
}); 
+1

Intenté agregar el fragmento de código de usted en mi código (puede encontrarlo aquí http: // stackoverflow .com/questions/3667442/how-to-refresh-adapter) en onCreate-method, pero aún así no tengo éxito :(Quizás era un lugar incorrecto para agregarlo ?! – Tima

+1

Tu pregunta simplemente me preguntó cómo puedes llamar el método y ejecutarlo en el hilo principal de la interfaz de usuario. Esto responde a esa pregunta. En su caso particular (http://stackoverflow.com/questions/3670500/notifydatasetchanged-doesnt-work/3670861#3670861) AsyncTask y su onPostExecute() método parece ser lo que debe considerar. – Brian

6

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

Añadir este donde normalmente (intentar) llamar a 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); 
     } 
    } 
} 
+0

Tengo un par de otros ArrayAdapters en mi código y han funcionado sin problemas. Esta noche, decidí convertir un SimpleCursorAdapter en un ArrayAdapter, 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É instanciaste una nueva clase para ello? – techiServices

+2

En las funciones de Java se llaman métodos. ¿Qué propondrías, 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 puede ser reutilizado. Si quieres que sea estático, por supuesto, adelante. –

9

Hace poco escribí sobre este tema, aunque este post es viejo, pensé que será útil para alguien que quiere saber cómo implementar BaseAdapter.notifyDataSetChanged() paso a paso y de manera correcta.

Por favor, siga How to correctly implement BaseAdapter.notifyDataSetChanged() in Android o the newer blog BaseAdapter.notifyDataSetChanged().

+0

Hola, probé primero el ejemplo de enlace, pero en vez de 'mItem.add()', he hecho simplemente editar un elemento como 'mItem.get (posición) .setImage (encodedImage) 'puede ser por eso que está dando error NullPointer exeption.So not notifyDataSetChange funciona en solo editarlo, bcz para adaptador Array se menciona arriba, solo funciona para add(), clear(), remove () etc. –

+0

notifyDataSetChanged funcionará para editar o modificar el conjunto de datos, su puntero nulo se debe a otra cosa, verifique los registros. –

2

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

Así que mi situación fue la siguiente.

Tuve que actualizar una vista de lista en una pestaña de la barra de acciones (fragmento) con los contenidos devueltos 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 regresé 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() del 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 volvería a algunos datos FragmentTab2 y sería actualizar directamente a mi vista de lista en FragmentTab2.

Espero que alguien encuentre esto útil!