My ListFragment code
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 se ItemAdapter
extiendeBaseAdapter
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?
android
android-listview
notifydatasetchanged
Descifrador
fuente
fuente
adapter
referencia, ¿por qué lo prueba para nulo una línea a continuación?Respuestas:
Mira tu
onResume
método enItemFragment
:lo que acaba de actualizar antes de llamar
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 onCreate del fragmento). La forma más corta (en el sentido de la cantidad de cambios) pero no elegante de hacer que su código se comporte como espera es simplemente reemplazar la línea:con
Una solución más elegante:
1) eliminar elementos
private List<Item> items;
deItemFragment
: debemos mantener la referencia a ellos solo en el adaptador2) cambie onCreate a:
3) agregue el método en ItemAdapter:
4) cambie su onResume a:
fuente
adapter.swapItems();
y el adaptador haría lasdbHelper.getItems()
cosas. Pero de todos modos gracias por la respuesta :)notifyDataSetChanged()
?Está asignando elementos recargados a elementos de variables globales en
onResume()
, pero esto no se reflejará en laItemAdapter
clase, porque tiene su propia variable de instancia llamada 'elementos'.Para actualizar
ListView
, agregue un refresh () en laItemAdapter
clase que acepta datos de lista, es decir, elementosactualizar
onResume()
con el siguiente códigofuente
En onResume () cambia esta línea
a
El problema es que nunca le dice a su adaptador sobre la lista de elementos nuevos. Si no desea pasar una nueva lista a su adaptador (ya que parece que no lo hace), use
items.addAll
después de suclear()
. Esto asegurará que está modificando la misma lista a la que hace referencia el adaptador.fuente
adapter.clear()
no obliga al adaptador de darse cuenta de que debe refrescar la vista, peroadapter.add()
oadapter.addAll()
lo hace. ¡Gracias por la respuesta!items.addAll()
y no adaptor.addAll (). Lo único que permite que el adaptador reaccione a los cambios es elnotifyDataSetChanged
. La razón por la que el adaptador ve cambios es que laitems
lista es la misma lista que está usando el adaptador.Si el adaptador ya está configurado, volver a configurarlo no actualizará la vista de lista. En su lugar, primero verifique si la vista de lista tiene un adaptador y luego llame al método apropiado.
Creo que no es muy buena idea crear una nueva instancia del adaptador mientras configura la vista de lista. En su lugar, cree un objeto.
También puede intentar ejecutar la lista de actualización en el hilo de la interfaz de usuario:
fuente
ItemAdapter
es que quiero colorear las filas y la vista de lista muestra varios elementos de datos. He publicado el código del adaptador.Si desea actualizar su vista de lista, no importa si desea hacerlo en
onResume()
,onCreate()
o en alguna otra función, lo primero que debe tener en cuenta es que no necesitará crear una nueva instancia del adaptador, solo complete las matrices con sus datos nuevamente. La idea es algo similar a esto:Entonces, dependiendo de esa respuesta, debe usar la misma
List<Item>
en suFragment
. En la primera inicialización de su adaptador, complete su lista con los elementos y configure el adaptador en su vista de lista. Después de eso, en cada cambio en sus elementos, debe borrar los valores del archivo principalList<Item> items
y luego completarlo nuevamente con sus nuevos elementos y llamarnotifySetDataChanged();
.Asi es como funciona : ).
fuente
Una respuesta de AlexGo hizo el truco para mí:
List Update funcionó para mí antes cuando la actualización se activó desde un evento de GUI, por lo que estaba en el hilo de la interfaz de usuario.
Sin embargo, cuando actualizo la lista desde otro evento / hilo, es decir, una llamada desde fuera de la aplicación, la actualización no estaría en el hilo de la interfaz de usuario e ignoró la llamada a getListView. Llamar a la actualización con runOnUiThread como arriba funcionó para mí. ¡¡Gracias!!
fuente
Prueba esto
fuente
Pruebe esto en el
onPause()
método de la clase Activity.fuente
debería hacer el truco.
fuente
Si su lista está contenida en el propio Adaptador, llamar a la función que actualiza la lista también debería llamar
notifyDataSetChanged()
.Ejecutar esta función desde el subproceso de la interfaz de usuario hizo el truco para mí:
La
refresh()
función dentro del AdaptadorLuego, a su vez, ejecute esta función desde el hilo de la interfaz de usuario
fuente
Intente así:
en vez de:
Tienes que
notifyDataSetChanged()
alListView
no a la clase adaptador.fuente