Reciclaje de vistas en adaptador de arreglo personalizado: ¿cómo se maneja exactamente?

Tengo un problema claro sobre el reciclaje de vistas en un método getView de un adaptador de matriz personalizado.

Entiendo que los elementos se reutilizan, pero ¿cómo sé exactamente qué implementar en la primera parte de la declaración if, y qué en el segundo?

Ahora mismo estoy teniendo el siguiente código. He llegado a esta pregunta debido a la caída del código en la segunda parte de la declaración que da lugar a una lista de los primeros 9 elementos, que se repiten varias veces en lugar de todos los elementos. Realmente no sabía lo que está causando esto exactamente …

@Override public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; if (row == null) { LayoutInflater inflater = ((Activity) context).getLayoutInflater(); row = inflater.inflate(layoutResourceId, parent, false); title = getItem(position).getTitle(); size = calculateFileSize(position); txtTitle = (TextView) row.findViewById(R.id.txtTitle); tvFileSize = (TextView) row.findViewById(R.id.tvFileSize); txtTitle.setText(title); tvFileSize.setText(size); } else { title = getItem(position).getTitle(); size = calculateFileSize(position); txtTitle = (TextView) row.findViewById(R.id.txtTitle); tvFileSize = (TextView) row.findViewById(R.id.tvFileSize); txtTitle.setText(title); tvFileSize.setText(size); } return row; } 

Entiendo que los elementos se reutilizan, pero ¿cómo sé exactamente qué implementar en la primera parte de la declaración if, y qué en el segundo?

La organización es bastante simple una vez que usted consigue el cuelgue de ella:

 public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { /* This is where you initialize new rows, by: * - Inflating the layout, * - Instantiating the ViewHolder, * - And defining any characteristics that are consistent for every row */ } else { /* Fetch data already in the row layout, * primarily you only use this to get a copy of the ViewHolder */ } /* Set the data that changes in each row, like `title` and `size` * This is where you give rows there unique values. */ return convertView; } 

Para obtener explicaciones detalladas de cómo funciona ListView RecycleBin y por qué ViewHolders son importantes ver Turbo Cargar su interfaz de usuario , una presentación de Google I / O por los programadores de ListView de Android.

Es fácil. La primera vez que no se crea ninguna fila, es necesario inflarlas. Posteriormente, el sistema operativo Android puede decidir reciclar las vistas que ya infló y que ya no son visibles. Aquellos ya están inflados y pasados ​​al parámetro convertView, así que todo lo que tienes que hacer es organizarlo para mostrar el nuevo elemento actual, por ejemplo colocando los valores correctos en los distintos campos de texto.

Introduzca aquí la descripción de la imagen

En resumen, en la primera parte se debe realizar la inflación y llenar los valores, en el segundo if ( if convertView != null ) sólo debe sobrescribir el campo porque, dado que la vista ha sido reciclado, las vistas de texto contienen los valores de la Artículo viejo.

Este post y esto son buenos puntos de partida

Desea crear una clase ViewHolder en MainActivity . Algo como

  static class ViewHolder { TextView tv1; TextView tv2; } 

Entonces en su getView , la primera vez que obtiene sus Views de su xml en el if y reutilizarlos después de que en el else

 View rowView = convertView; if (rowView == null) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); rowView = inflater.inflate(R.layout.layout_name_to_inflate, parent, false); holder = new ViewHolder(); holder.tv1= (TextView) rowView.findViewById(R.id.textView1); holder.tv2 = (RadioGroup) rowView.findViewById(R.id.textView2); rowView.setTag(holder); } else { holder = (ViewHolder) rowView.getTag(); } 

Recomendaría que usted utilice el sostenedor de la visión y el patrón del convertview para crear su listView mientras que será más eficiente. Esta es una buena explicación de cómo funciona con una estrategia de reutilización. Esto responderá a su pregunta sobre cómo funciona el reciclaje. Si desea referirse a un código de ejemplo, lo tengo en GitHub .

Espero que esto ayude.

La última parte de la pregunta que realmente no podía comprender sin una imagen del efecto, pero para la primera parte "qué implementar en la primera parte de la declaración if, y lo que en el segundo" Creo que he encontrado el presente Aplicación muy común.

Encontrará las referencias de vista primero y almacenarlas en una clase estática ViewHolder que luego adjuntará a la etiqueta de la nueva vista inflada. Como el listview recicla las vistas y un convertView se pasa getView usted obtiene el ViewHolder de la convertView del convertView para que no tenga que encontrar las referencias de nuevo (lo que mejora el rendimiento) y actualizar los datos de vista con la de su objeto en La posición dada.

Técnicamente no le importa qué posición de la vista era ya que todo lo que importa es las referencias a las vistas que necesita para actualizar que se celebran en su ViewHolder.

 @Override public View getView(int position, View convertView, ViewGroup container) { ViewHolder holder; Store store = getItem(position); if (convertView == null) { convertView = mLayoutInflater.inflate(R.layout.item_store, null); // create a holder to store references holder = new ViewHolder(); // find references and store in holder ViewGroup logoPhoneLayout = (ViewGroup) convertView .findViewById(R.id.logophonelayout); ViewGroup addressLayout = (ViewGroup) convertView .findViewById(R.id.addresslayout); holder.image = (ImageView) logoPhoneLayout .findViewById(R.id.image1); holder.phone = (TextView) logoPhoneLayout .findViewById(R.id.textview1); holder.address = (TextView) addressLayout .findViewById(R.id.textview1); // store holder in views tag convertView.setTag(holder); } else { // Retrieve holder from view holder = (ViewHolder) convertView.getTag(); } // fill in view with our store (at this position) holder.phone.setText(store.phone); holder.address.setText(store.getFullAddress()); UrlImageViewHelper.setUrlDrawable(holder.image, store.storeLogoURL, R.drawable.no_image); return convertView; } private static class ViewHolder { ImageView image; TextView phone; TextView address; } 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.