Android ListView no se actualiza después de notifyDataSetChanged

Mi código ListFragment

public class ItemFragment extends ListFragment { private DatabaseHandler dbHelper; private static final String TITLE = "Items"; private static final String LOG_TAG = "debugger"; private ItemAdapter adapter; private List<Item> items; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.item_fragment_list, container, false); return view; } @Override public void onCreate(Bundle savedInstanceState) { super.setHasOptionsMenu(true); super.onCreate(savedInstanceState); getActivity().setTitle(TITLE); dbHelper = new DatabaseHandler(getActivity()); items = dbHelper.getItems(); adapter = new ItemAdapter(getActivity().getApplicationContext(), items); this.setListAdapter(adapter); } @Override public void onResume() { super.onResume(); items.clear(); items = dbHelper.getItems(); //reload the items from database adapter.notifyDataSetChanged(); } @Override public void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); if(dbHelper != null) { //item is edited Item item = (Item) this.getListAdapter().getItem(position); Intent intent = new Intent(getActivity(), AddItemActivity.class); intent.putExtra(IntentConstants.ITEM, item); startActivity(intent); } } } 

Mi ListView

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ListView android:id="@android:id/list" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> 

Pero esto no actualiza el ListView . Incluso después de reiniciar la aplicación los elementos actualizados no se muestran. Mi ItemAdapter extiende BaseAdapter

 public class ItemAdapter extends BaseAdapter{ private LayoutInflater inflater; private List<Item> items; private Context context; public ProjectListItemAdapter(Context context, List<Item> items) { super(); inflater = LayoutInflater.from(context); this.context = context; this.items = items; } @Override public int getCount() { return items.size(); } @Override public Object getItem(int position) { return items.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ItemViewHolder holder = null; if(convertView == null) { holder = new ItemViewHolder(); convertView = inflater.inflate(R.layout.list_item, parent,false); holder.itemName = (TextView) convertView.findViewById(R.id.topText); holder.itemLocation = (TextView) convertView.findViewById(R.id.bottomText); convertView.setTag(holder); } else { holder = (ItemViewHolder) convertView.getTag(); } holder.itemName.setText("Name: " + items.get(position).getName()); holder.itemLocation.setText("Location: " + items.get(position).getLocation()); if(position % 2 == 0) { convertView.setBackgroundColor(context.getResources().getColor(R.color.evenRowColor)); } else { convertView.setBackgroundColor(context.getResources().getColor(R.color.oddRowColor)); } return convertView; } private static class ItemViewHolder { TextView itemName; TextView itemLocation; } } 

¿Puede alguien ayudar, por favor?

11 Solutions collect form web for “Android ListView no se actualiza después de notifyDataSetChanged”

Mire su método ItemFragment en ItemFragment :

 @Override public void onResume() { super.onResume(); items.clear(); items = dbHelper.getItems(); // reload the items from database adapter.notifyDataSetChanged(); } 

Lo que acaba de actualizar antes de llamar a notifyDataSetChanged() no es el campo del adaptador private List<Item> items; Sino el campo idénticamente declarado del fragmento. El adaptador todavía almacena una referencia a la lista de elementos que pasó cuando creó el adaptador (por ejemplo, en el fragmento onCreate). El más corto (en el sentido de número de cambios) pero no manera elegante de hacer que su código se comporte como usted espera es simplemente reemplazar la línea:

  items = dbHelper.getItems(); // reload the items from database 

con

  items.addAll(dbHelper.getItems()); // reload the items from database 

Una solución más elegante:

1) eliminar elementos private List<Item> items; De ItemFragment – necesitamos mantener la referencia a ellos sólo en el adaptador

2) cambiar aCriar a:

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setHasOptionsMenu(true); getActivity().setTitle(TITLE); dbHelper = new DatabaseHandler(getActivity()); adapter = new ItemAdapter(getActivity(), dbHelper.getItems()); setListAdapter(adapter); } 

3) agregue el método en ItemAdapter:

 public void swapItems(List<Item> items) { this.items = items; notifyDataSetChanged(); } 

4) cambie su onResume a:

 @Override public void onResume() { super.onResume(); adapter.swapItems(dbHelper.getItems()); } 

Está asignando elementos recargados a elementos variables globales en onResume() , pero esto no se reflejará en la clase ItemAdapter porque tiene su propia variable de instancia llamada 'items'.

Para actualizar ListView , agregue una actualización () en la clase ItemAdapter que acepta datos de lista, es decir, elementos

 class ItemAdapter { ..... public void refresh(List<Item> items) { this.items = items; notifyDataSetChanged(); } } 

Actualizar onResume() con el siguiente código

 @Override public void onResume() { super.onResume(); items.clear(); items = dbHelper.getItems(); //reload the items from database **adapter.refresh(items);** } 

En onResume () cambia esta línea

 items = dbHelper.getItems(); //reload the items from database 

a

 items.addAll(dbHelper.getItems()); //reload the items from database 

El problema es que nunca le dices a tu adaptador sobre la nueva lista de elementos. Si no desea pasar una nueva lista a su adaptador (como parece que no), entonces sólo use items.addAll después de su clear() . Esto asegurará que está modificando la misma lista a la que el adaptador tiene una referencia.

Si el adaptador ya está configurado, volver a configurarlo no actualizará la vista de lista. En su lugar primero compruebe si el listview tiene un adaptador y luego llame al método apropiado.

Creo que no es una muy buena idea crear una nueva instancia del adaptador mientras se establece la vista de lista. En su lugar, cree un objeto.

 BuildingAdapter adapter = new BuildingAdapter(context); if(getListView().getAdapter() == null){ //Adapter not set yet. setListAdapter(adapter); } else{ //Already has an adapter adapter.notifyDataSetChanged(); } 

También puede intentar ejecutar la lista de actualizaciones en la interfaz de usuario Tema:

 activity.runOnUiThread(new Runnable() { public void run() { //do your modifications here // for example adapter.add(new Object()); adapter.notifyDataSetChanged() } }); 

Si quieres actualizar tu listview no importa si quieres hacer eso en onResume() , onCreate() o en alguna otra función, lo primero que tienes que darse cuenta es que no necesitas crear una nueva instancia Del adaptador, sólo rellenar los arrays con los datos de nuevo. La idea es algo similar a esto:

 private ArrayList<String> titles; private MyListAdapter adapter; private ListView myListView; @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main_activity); myListView = (ListView) findViewById(R.id.my_list); titles = new ArrayList<String>() for(int i =0; i<20;i++){ titles.add("Title "+i); } adapter = new MyListAdapter(this, titles); myListView.setAdapter(adapter); } @Override public void onResume(){ super.onResume(); // first clear the items and populate the new items titles.clear(); for(int i =0; i<20;i++){ titles.add("New Title "+i); } adapter.notifySetDataChanged(); } 

Así que dependiendo de esa respuesta, debes usar la misma List<Item> en tu Fragment . En la primera inicialización del adaptador, llena su lista con los elementos y establece el adaptador en su lista. Después de cada cambio en sus elementos, tiene que borrar los valores de los elementos principales de List<Item> items y volver a rellenarlos con sus nuevos elementos y llamar a notifySetDataChanged(); .

Asi es como funciona : ).

Una respuesta de AlexGo hizo el truco para mí:

 getActivity().runOnUiThread(new Runnable() { @Override public void run() { messages.add(m); adapter.notifyDataSetChanged(); getListView().setSelection(messages.size()-1); } }); 

La Actualización de la lista funcionó para mí cuando la actualización se activó desde un evento GUI, por lo que estaba en el subproceso de la interfaz de usuario.

Sin embargo, cuando actualizo la lista de otro evento / subproceso, es decir, una llamada desde fuera de la aplicación, la actualización no estaría en el subproceso de IU e ignoraría la llamada a getListView. Llamar a la actualización con runOnUiThread como anteriormente hizo el truco para mí. ¡¡Gracias!!

Prueba esto

 @Override public void onResume() { super.onResume(); items.clear(); items = dbHelper.getItems(); //reload the items from database adapter = new ItemAdapter(getActivity(), items);//reload the items from database adapter.notifyDataSetChanged(); } 
 adpter.notifyDataSetInvalidated(); 

Pruebe esto en el método onPause() de la clase Activity.

 adapter.setNotifyDataChanged() 

Debe hacer el truco.

Prueba de esta manera:

 this.notifyDataSetChanged(); 

en lugar de:

 adapter.notifyDataSetChanged(); 

Tienes que notifyDataSetChanged() a ListView no a la clase del adaptador.

Si su lista está contenida en el propio adaptador, llamar a la función que actualiza la lista también debe llamar a notifyDataSetChanged() .

Ejecutar esta función de la interfaz de usuario Hilo hizo el truco para mí:

La función refresh() dentro del adaptador

 public void refresh(){ //manipulate list notifyDataSetChanged(); } 

A su vez, ejecute esta función desde el subproceso de interfaz de usuario

 getActivity().runOnUiThread(new Runnable() { @Override public void run() { adapter.refresh() } }); 
  • ¿Quieres implementar notifyDataSetChanged o autorefresh a mi RecyclerView pero no funciona
  • Cómo añadir sugerencias dinámicamente a autocompletetextview con preservar el estado de los caracteres
  • Cómo proporcionar animación personalizada durante la clasificación (notifyDataSetChanged) en RecyclerView
  • Android: detecta si un ListView tiene la barra de desplazamiento (después de configurar nuevos datos)
  • Cómo evitar la renovación de las celdas al llamar a notifyDataSetChanged () para PinterestLikeAdapterView?
  • Mantener el foco en TextView después de notifyDatasetChanged () fue llamado en listview personalizado?
  • ¿Por qué no necesito usar Adapter.notifyDataSetChanged ()?
  • Android getChildView no se llama después de notifyDataSetChanged
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.