Android listview muestra datos falsos después de desplazarse (adaptador personalizado)

Tengo un extraño problema que me vuelve loco. En mi aplicación Android, personalizé mi propio adaptador que se extiende desde ArrayAdapter. Los elementos de ListView a los que he añadido mi adaptador pueden ser etiquetados-texto (no editable), texto editable o un hilandero. La locura es: cuando se desplaza el ListView, hay dos problemas:

(1) el valor (seleccionado) que se muestra en los elementos del hilandero cambia a veces aunque solo hice scroll! Cuando hago clic en la ruleta, el valor seleccionado antiguo todavía se muestra (el que debe ser mostrado por la ruleta) (2) el orden de los cambios ListViewItems cuando me desplácese!

=> PERO los datos en el adaptador no cambian (ni los datos en sí ni la orden) – por lo que debe ser un problema de la propia vista ?! Tal vez cachés androides en el fondo y no actualizar el ListViewItems pronto o algo así ?!

puede alguien ayudarme por favor?

¡Muchas gracias!

Ok, he encontrado una solución que no es muy agradable, pero funciona. Simplemente no uso convertView más aunque es subóptimo en relación con la memoria y el rendimiento. En mi caso, debería estar bien porque la cantidad máxima de mis ListView es 15. Aquí está mi Adapter-Class:

public class FinAdapter extends ArrayAdapter<Param>{ public Param[] params; private boolean merkzettel; protected EditText pv; public FinAdapter(Context context, int textViewResourceId, Param[] items, boolean merkzettel) { super(context, textViewResourceId, items); this.params = items; this.merkzettel = merkzettel; } @Override public View getView(int position, View convertView, ViewGroup parent) { final Param p = params[position]; if(p != null){ if(merkzettel){ if (convertView == null) { LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = vi.inflate(R.layout.merk_det_item, null); } TextView tvl = (TextView) convertView.findViewById(R.id.paramM); TextView edl = (TextView) convertView.findViewById(R.id.param_valueM); TextView pal = (TextView) convertView.findViewById(R.id.param_unitM); if (tvl != null) { tvl.setText(p.getName()); } if(pal != null){ pal.setText(p.getUnit()); } if(edl != null){ edl.setText(p.getDefData()); } } else{ if(p.isSelect()){ if (convertView == null) { LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = vi.inflate(R.layout.fin_prod_list_item_select, null); } TextView tvs = (TextView) convertView.findViewById(R.id.paramS); Spinner sp = (Spinner) convertView.findViewById(R.id.spinner_kalk); TextView paU = (TextView) convertView.findViewById(R.id.param_unitS); if (tvs != null) { tvs.setText(p.getName()); } if(paU != null){ paU.setText(p.getUnit()); } if(sp != null){ String[] values = new String[p.getData().size()]; for(int i=0; i<values.length; i++){ values[i] = p.getData().get(i); } ArrayAdapter<String> adapter = new ArrayAdapter<String>(this.getContext(), android.R.layout.simple_spinner_item, values); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); sp.setAdapter(adapter); sp.setSelection(p.getData().indexOf(p.getDefData())); sp.setOnItemSelectedListener(new OnItemSelectedListener(){ public void onItemSelected(AdapterView<?> parent, View convertView, int pos, long id) { p.setDefData(p.getData().get(pos)); p.setChanged(true); } public void onNothingSelected(AdapterView<?> arg0) { // TODO Auto-generated method stub } }); } } else if(p.isEdit()){ if (convertView == null) { LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = vi.inflate(R.layout.fin_prod_list_item_edit, null); } TextView pa = (TextView) convertView.findViewById(R.id.param); pv = (EditText) convertView.findViewById(R.id.param_value); TextView paE = (TextView) convertView.findViewById(R.id.param_unit); if (pa != null) { pa.setText(p.getName()); } if(paE != null){ paE.setText(p.getUnit()); } if(pv != null){ pv.setText(p.getDefData()); pv.setOnEditorActionListener(new OnEditorActionListener(){ public boolean onEditorAction(TextView convertView, int actionId, KeyEvent event) { // TODO Auto-generated method stub p.setDefData(pv.getText().toString()); p.setChanged(true); return false; } }); } } else if(p.isLabel()){ if (convertView == null) { LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = vi.inflate(R.layout.fin_prod_list_item_label, null); } TextView tvl = (TextView) convertView.findViewById(R.id.paramL); TextView edl = (TextView) convertView.findViewById(R.id.param_valueL); TextView pal = (TextView) convertView.findViewById(R.id.param_unitL); if (tvl != null) { tvl.setText(p.getName()); } if(pal != null){ pal.setText(p.getUnit()); } if(edl != null){ edl.setText(p.getDefData()); } }} } return convertView; } } 

2 Solutions collect form web for “Android listview muestra datos falsos después de desplazarse (adaptador personalizado)”

Tuve un problema similar con varios tipos de elementos en la lista. En mi caso, el elemento de lista era un elemento de sección (etiqueta) o un elemento de lista común.

Para trabajar con estos tipos de listas, debe reemplazar los métodos getViewTypeCount y getItemViewType . Algo como esto:

 private static final int ITEM_VIEW_TYPE_ITEM = 0; private static final int ITEM_VIEW_TYPE_SEPARATOR = 1; @Override public int getViewTypeCount() { return 2; } @Override public int getItemViewType(int position) { return this.getItem(position).isSection() ? ITEM_VIEW_TYPE_SEPARATOR : ITEM_VIEW_TYPE_ITEM; } @Override public View getView(int position, View convertView, ViewGroup parent) { final Item item = this.getItem(position); if (convertView == null) { convertView = mInflater.inflate(item.isSection() ? R.view1 : R.view2, null); } if(item.isSection()){ //... } else{ //... } return convertView; } 

Entonces el parámetro convertView siempre será correcto y contendrá ese tipo que usted necesita.

Y otra cosa: agregó explícitamente el public Param[] params campo cuando ya lo tiene en la clase base ArrayAdapter<Param> .

Recomendaría heredar de la clase BaseAdapter .

Edit: Este es el código que puedes intentar usar para hacer que tu Spinner funcione:

 sp.setTag(p); sp.setOnItemSelectedListener(new OnItemSelectedListener(){ public void onItemSelected(AdapterView<?> parent, View convertView, int pos, long id) { Param currentItem = (Param)parent.getTag(); currentItem.setDefData(currentItem.getData().get(pos)); currentItem.setChanged(true); } //... 

Intente utilizar la combinación de los métodos getTag y setTag . Recuerdo que tuve problemas similares con manejadores de eventos y variables finales, pero olvidé por completo la causa de ellos, así que no puedo explicar exactamente por qué sucede esto.

Como se mencionó por Sam, el sistema Android siempre intenta reciclar si es posible para conservar los recursos. Esto significa que los desarrolladores necesitan realizar un seguimiento de la View en ListView ellos mismos. Para la entidad, o la denominada estructura de datos de presentación, puede tener algo que realizar un seguimiento del estado seleccionado / no seleccionado, por ejemplo:

 class PresentationData { // other stuffs.. boolean isSelected = false; } 

Asignar estas estructuras de datos al Adapter y si se ha hecho clic en algún elemento, establezca el estado en verdadero: listPresentationData.get(selected_position).isSelected = true

Ok así que en el getView() del adaptador, realizar un seguimiento de la presentación correctamente para sus datos.

 if(listPresentationData.get(position).isSelected) { // set background color of the row layout..or something else } 

Además, vale la pena mencionar que es mejor tener un caché de memoria para cada vista, generalmente llamada ViewHolder para mejorar el rendimiento también.

  • Cómo dibujar un encabezado de sección en android listview al igual que el UITableview del ios?
  • Getview parámetro "convertview" no nulo en el nuevo parámetro "posición"
  • Problemas de procesamiento Excepción generada durante la renderización: las matrices de color y posición deben tener la misma longitud
  • Cómo poner los elementos de la lista en la parte inferior de la vista de lista en el Cajón de navegación como Foursquare
  • Se ha intentado finalizar un evento de entrada pero el receptor de eventos de entrada ya se ha eliminado
  • MVVMCross Obtener SelectedItem de un MvxBindableListView
  • ¿Cómo puedo obtener uri del elemento ListView que se rellena con Cursor Adapter
  • ¿Cómo hacer gradiente transparente?
  • Cambiar el color de fondo del primer elemento en ListView
  • ¿Cómo puedo quitar el teclado después de terminar una actividad?
  • Haga clic en la casilla de verificación de listItem
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.