BaseAdapter que hace que ListView salga de orden cuando se desplaza

Tengo problemas con algún código de BaseAdapter que adapté de un libro. He estado utilizando variaciones de este código en todo el lugar de mi aplicación, pero sólo se dio cuenta cuando se desplaza una lista larga de los elementos en el ListView se mezclan y no todos los elementos se muestran.

Es muy difícil describir el comportamiento exacto, pero es fácil ver si se toma una lista ordenada de 50 elementos y empieza a desplazarse hacia arriba y hacia abajo.

class ContactAdapter extends BaseAdapter { ArrayList<Contact> mContacts; public ContactAdapter(ArrayList<Contact> contacts) { mContacts = contacts; } @Override public int getCount() { return mContacts.size(); } @Override public Object getItem(int position) { return mContacts.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view; if(convertView == null){ LayoutInflater li = getLayoutInflater(); view = li.inflate(R.layout.groups_item, null); TextView label = (TextView)view.findViewById(R.id.groups_item_title); label.setText(mContacts.get(position).getName()); label = (TextView)view.findViewById(R.id.groups_item_subtitle); label.setText(mContacts.get(position).getNumber()); } else { view = convertView; } return view; } } 

2 Solutions collect form web for “BaseAdapter que hace que ListView salga de orden cuando se desplaza”

Sólo se están poniendo datos en los widgets de TextView cuando se crean por primera vez. Necesitas mover estas cuatro líneas:

  TextView label = (TextView)view.findViewById(R.id.groups_item_title); label.setText(mContacts.get(position).getName()); label = (TextView)view.findViewById(R.id.groups_item_subtitle); label.setText(mContacts.get(position).getNumber()); 

Para estar después del bloque if / else y antes del retorno del método, por lo que actualiza los widgets TextView si está reciclando la fila o creando una nueva.

Para aclarar más la respuesta de CommonsWare, aquí hay más información:

La operación li.inflate (necesaria aquí para analizar el diseño de una fila de XML y crear el objeto de vista apropiado) está envuelta por una instrucción if (convertView == null) para la eficiencia, por lo que no sucederá la inflación del mismo objeto Una y otra vez cada vez que aparece a la vista.

SIN EMBARGO, las otras partes del método de getView se utilizan para fijar otros parámetros y por lo tanto NO se deben incluir en la instrucción if (convertView == null) {} … else {} .

En muchas implementaciones comunes de este método, algunos elementos textView, ImageView o ImageButton necesitan ser poblados por valores de la lista [position], usando findViewById y después de las operaciones .setText o .setImageBitmap . Estas operaciones deben venir después de crear una vista desde cero por inflación y obtener una vista existente si no es nula (por ejemplo, en una actualización).

Otro buen ejemplo donde se aplica esta solución para un ListView ArrayAdapter aparece en https://stackoverflow.com/a/3874639/978329

  • Android: deslizar el elemento de la lista causa clickOnItem
  • Android - Animación al eliminar elementos de ListView
  • android usando setlistadapter () sin extender listactivity
  • Seleccionar todos los elementos de ListView
  • Android EditText dentro de ListView?
  • ¿Cómo puedo aumentar el tamaño de la vista de mi lista?
  • Android ListView setSelectionFromTop no funciona
  • Ver en Android ListView no volver a dibujar
  • Android ListView: texto predeterminado cuando no hay elementos
  • Android ListView: detecta si los datos de ListView se ajustan a la pantalla sin desplazarse
  • Cómo controlar el número de vista previa de ListView en Android Studio
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.