¿Cuál es el beneficio de ViewHolder?

Cuando esté desarrollando un programa de Android; Y usted desea tener un ArrayAdapter usted puede tener simplemente una clase (la mayoría de veces con el sufijo de ViewHolder ) o inflar directamente su convertView y encontrar su opinión por el id.
¿Cuál es el beneficio de usar ViewHolder?
El ejemplo de ambos aquí:

if(convertView==null) { convertView = ((Activity)_context).getLayoutInflater().inflate(R.layout.row_phrase, null); } ((TextView)convertView.findViewById(R.id.txtPhrase)).setText("Phrase 01"); 

O:

 static class ViewHolder { ImageView leftIcon; TextView upperLabel; TextView lowerLabel; } 

Y finalmente en el getView:

 ViewHolder holder = null; if (view == null) { view = LayoutInflater.from(context).inflate(R.layout.row_layout, null, false); holder = new ViewHolder(); holder.leftIcon = (ImageView) view.findViewById(R.id.leftIcon); 

Entender cómo funciona el reciclaje listview

Cómo funciona el mecanismo de reciclaje de ListView

No puede reciclar una fila que esté actualmente en uso. El enlace anterior explica cómo funciona el mecanismo de reciclado listview

¿Cuál es el beneficio de usar ViewHolder?

Citando documentos

Su código puede llamar a findViewById() frecuencia durante el desplazamiento de ListView, lo que puede ralentizar el rendimiento. Incluso cuando el adaptador devuelve una vista inflada para reciclar, todavía necesita buscar los elementos y actualizarlos. Una forma de evitar el uso repetido de findViewById() es usar el patrón de diseño "view holder".

  public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { // if convertView is null convertView = mInflater.inflate(R.layout.mylayout, parent, false); holder = new ViewHolder(); // initialize views convertView.setTag(holder); // set tag on view } else { holder = (ViewHolder) convertView.getTag(); // if not null get tag // no need to initialize } //update views here return convertView; } 

Se ha perdido la parte importante convertView.setTag(holder) y holder = (ViewHolder) ConvertView.getTag()

http://developer.android.com/training/improving-layouts/smooth-scrolling.html

ViewHolder patrón de diseño de ViewHolder se utiliza para acelerar la representación de tu ListView – en realidad para que funcione sin problemas, findViewById es bastante costoso (se analiza el DOM) cuando se utiliza cada vez que se representa un elemento de lista, debe desplazar la jerarquía de diseño y también instanciar objetos . Dado que las listas pueden volver a dibujar sus elementos con bastante frecuencia durante el desplazamiento, tales gastos generales podrían ser sustanciales.

Usted puede encontrar una buena explicación de cómo esto funciona en:

http://www.youtube.com/watch?v=wDBM6wVEO70&feature=youtu.be&t=7m

A partir del minuto 10, usted ha explicado el patrón de diseño ViewHolder por los expertos de google.

[editar]

FindViewById no está instanciando nuevos objetos, solo atraviesa la jerarquía – aquí está la referencia http://androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/view/ViewGroup.java#3610

A medida que avanza a través de su ListView, sólo hay un puñado de puntos de vista que se muestran en un momento dado. Esto significa que no tiene que instanciar una vista para cada elemento de su adaptador; Cuando una vista se desplaza fuera de la pantalla, puede ser reutilizada o reciclada .

El reciclado de la vista y el patrón ViewHolder no son los mismos. El patrón ViewHolder es únicamente para reducir el número de view.findViewById(int) que realiza. El patrón ViewHolder sólo funciona cuando se aprovecha el reciclaje de vistas.

En getView(int position, View convertView, ViewGroup parent) , el parámetro convertView es nulo o es una vista que se ha reciclado: todavía tendrá los datos de un elemento de lista diferente vinculado a él.

Sin el patrón ViewHolder, todavía puede aprovechar el reciclado de la vista (es decir, no crear instancias de vistas de forma ciega):

 public View getView(int position, View convertView, ViewGroup parent) { View view = convertView; if (view == null) { view = // inflate new view } ImageView imageView = (ImageView) view.findViewById(R.id.listitem_image); TextView textView = (TextView) view.findViewById(R.id.listitem_text); TextView timestampView = (TextView) view.findViewById(R.id.listitem_timestamp); ProgressBar progressSpinnerView = (ProgressBar) view.findViewById(R.id.progress_spinner); // TODO: set correct data for this list item // imageView.setImageDrawable(...) // textView.setText(...) // timestampView.setText(...) // progressSpinnerView.setProgress(...) return view; } 

Arriba se muestra un ejemplo de reciclaje de vistas: no inflaremos una nueva vista para cada fila; Sólo inflamos una vista si no nos dan uno para reutilizar. Evitar tener que inflar una vista es la parte que definitivamente ayudará con el rendimiento al desplazarse por su lista: aproveche el reciclado de la vista.

Entonces, ¿cuál es el ViewHolder para entonces? Actualmente estamos haciendo 4x findViewById(int) para cada elemento, independientemente de si la fila misma ya existía. Como findViewById(int) itera recursivamente un ViewGroup hasta encontrar un descendiente con el ID dado, esto es un poco inútil para nuestras vistas recicladas – estamos buscando nuevas vistas a las que ya tenemos referencias.

Evite esto utilizando un objeto ViewHolder para mantener referencias a las sub-vistas después de "encontrarlas":

 private static class ViewHolder { final TextView text; final TextView timestamp; final ImageView icon; final ProgressBar progress; ViewHolder(TextView text, TextView timestamp, ImageView icon, ProgressBar progress) { this.text = text; this.timestamp = timestamp; this.icon = icon; this.progress = progress; } } 

View.setTag(Object) permite decir a la Vista que contenga un objeto arbitrario. Si lo usamos para mantener una instancia de nuestro ViewHolder después de hacer nuestras findViewById(int) , entonces podemos usar View.getTag() en las vistas reciclado para evitar tener que hacer las llamadas una y otra vez.

 public View getView(int position, View convertView, ViewGroup parent) { View view = convertView; if (view == null) { view = // inflate new view ViewHolder holder = createViewHolderFrom(view); view.setTag(holder); } ViewHolder holder = view.getTag(); // TODO: set correct data for this list item // holder.icon.setImageDrawable(...) // holder.text.setText(...) // holder.timestamp.setText(...) // holder.progress.setProgress(...) return view; } private ViewHolder createViewHolderFrom(View view) { ImageView icon = (ImageView) view.findViewById(R.id.listitem_image); TextView text = (TextView) view.findViewById(R.id.listitem_text); TextView timestamp = (TextView) view.findViewById(R.id.listitem_timestamp); ProgressBar progress = (ProgressBar) view.findViewById(R.id.progress_spinner); return new ViewHolder(text, timestamp, icon, progress); } 

Los beneficios de rendimiento de esta optimización son cuestionables , pero eso es el beneficio de ViewHolder .

En primer lugar :

En ListView cuando se desplaza el ListView necesita crear un nuevo elemento y enlazar sus datos en él así que si tiene muchos elementos en ListView puede causar pérdida de memoria porque más objetos que ha creado para los elementos, pero Android con el concepto de reciclar la mayor parte de su API , Y lo que significa que crear un objeto y utilizarlo en lugar de destruirlo y declarar uno nuevo, por lo que cuando se desplaza API de ListView utilizando los elementos invisibles que se despliegan y pasarlo para usted en el método convertView es convertView así que aquí usted trata con más elementos ListView

En segundo lugar:

Si tiene un elemento personalizado en ListView , debe adjuntar el diseño personalizado en cada elemento del ListView modo que cada vez que ListView vincule el nuevo elemento utilizando findViewById para obtener referencia de los elementos de diseño. Este método irá a buscar su artículo de manera recursiva para que ViewHolder le ayudará a hacer el recursivo hecho por una sola vez y luego mantendrá la referencia del elemento de diseño para usted hasta que pueda adjuntarlo para ListView

Espero que esto le ayude y me alimente de nuevo en cualquier cosa no obvia

  • Cómo mostrar datos de la lista Array a Custom ArrayAdapter
  • Crear una lista de ViewPager: elementos de la lista en blanco
  • Android - Destacar una palabra en un TextView?
  • Android-notifyDataSetChanged no funciona en BaseAdapter
  • Error: ArrayAdapter requiere que el ID de recurso sea un TextView
  • Android menuitem valor de retorno del manejador de onclick
  • Cómo controlar páginas de páginas de vista desde otra página
  • Artículos OnCreateContextMenu y ListView
  • Listview con Checkbox, RadioButton, Textview y el botón no funciona correctamente en android
  • NotifyDataSetChanged no puede actualizar ListView
  • ¿Es esto un listview, y cómo hacer esto
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.