Cómo cargar la Listview “smoothly” en android

Cargo datos de Cursor a la vista de lista, pero mi Listview realmente no muestra “sin problemas”. Los datos cambian cuando arrastro arriba y abajo en la barra scoll en mi ListView. Y algunos elementos parecen duplicados en mi lista. Tengo un “ListView complejo” (dos textview, one imageview) Así que utilicé newView (), bindView () para visualizar datos. ¿Alguien me puede ayudar?

Te describiré cómo obtener el problema que tienes. Posiblemente esto te ayudará.

Entonces, en el adaptador de lista tienes dicho código:

public View getView(int position, View contentView, ViewGroup arg2) { ViewHolder holder; if (contentView == null) { holder = new ViewHolder(); contentView = inflater.inflate(R.layout.my_magic_list,null); holder.label = (TextView) contentView.findViewById(R.id.label); contentView.setTag(holder); } else { holder = (ViewHolder) contentView.getTag(); } holder.label.setText(getLabel()); return contentView; } 

Como puede ver, establecemos el valor del elemento de la lista solo después de recuperar el titular.

Pero si mueve el código a la statement if anterior:

 holder.label.setText(getLabel()); 

por lo que se verá como a continuación:

 if (contentView == null) { holder = new ViewHolder(); contentView = inflater.inflate(R.layout.my_magic_list,null); holder.label = (TextView) contentView.findViewById(R.id.label); holder.label.setText(getLabel()); contentView.setTag(holder); } 

tendrá el comportamiento de su aplicación actual con la duplicación de elementos de la lista.

Posiblemente ayudará.

ListView es una bestia complicada.

Su segunda pregunta primero: está viendo duplicados porque ListView vuelve a utilizar Views a través de convertView, pero no se asegura de restablecer todos los aspectos de la vista convertida. Asegúrese de que la ruta del código para convertView!=null establece correctamente todos los datos para la vista, y todo debería funcionar correctamente.

getView() su método getView() se parezca más o menos al siguiente si está usando vistas personalizadas:

 @Override public View getView(int position, View convertView, ViewGroup parent) { final MyCustomView v = convertView!=null ? (MyCustomView)convertView : new MyCustomView(); v.setMyData( listAdapter.get(position) ); return v; } 

Si no está utilizando su propia vista personalizada, simplemente reemplace la llamada a la new MyCustomView() con una llamada a inflater.inflate(R.layout.my_layout,null)

En cuanto a su primera pregunta, querrá ver el techtalk de Romain sobre el rendimiento de ListView aquí: http://code.google.com/events/io/sessions/TurboChargeUiAndroidFast.html

De su charla y en orden de importancia de mi propia experiencia,

  • Use convertView
  • Si tiene imágenes, no escale sus imágenes sobre la marcha. Utilice Bitmap.createScaledBitmap para crear un bitmap escalado y poner eso en sus puntos de vista
  • Use un ViewHolder para no tener que llamar a un grupo de findViewByIds () cada vez
  • Disminuya la complejidad de las vistas en su lista. Cuantas menos subvistas, mejor. RelativeLayout es mucho mejor en esto que, por ejemplo, LinearLayout. Y asegúrate de usarlo si estás implementando vistas personalizadas.

También estoy enfrentando este problema, pero en mi caso usé hilos para buscar las imágenes externas. ¡Es importante que el hilo de ejecución actual no cambie la imagen vista si se reutiliza!

 public View getView(int position, View vi, ViewGroup parent) { ViewHolder holder; String imageUrl = ...; if (vi == null) { vi = inflater.inflate(R.layout.tweet, null); holder = new ViewHolder(); holder.image = (ImageView) vi.findViewById(R.id.row_img); ... vi.setTag(holder); } else { holder = (ViewHolder) vi.getTag(); } holder.image.setTag(imageUrl); ... DRAW_MANAGER.fetchDrawableOnThread(imageUrl, holder.image); } 

Y luego, en el hilo de búsqueda estoy haciendo la comprobación importante :

 final Handler handler = new Handler() { @Override public void handleMessage(Message message) { // VERY IMPORTANT CHECK if (urlString.equals(url)) imageView.setImageDrawable((Drawable) message.obj); }; Thread thread = new Thread() { @Override public void run() { Drawable drawable = fetchDrawable(urlString); if (drawable != null) { Message message = handler.obtainMessage(1, drawable); handler.sendMessage(message); } }}; thread.start(); 

También se podría cancelar el hilo actual si su vista se reutiliza (como se describe aquí ), pero decidí no hacerlo porque quiero llenar mi caché para su posterior reutilización.

Solo un consejo: NUNCA use el fondo transparente del diseño del elemento, ya que ralentiza el rendimiento

Puede ver el texto de repetición en varias filas si lo maneja de forma incorrecta. Recientemente publiqué un blog sobre este tema, mira aquí . Aparte de eso, es posible que desee echarle un vistazo a la optimización del rendimiento de ListView . Generalmente se debe a la reutilización de vistas y ya lo he visto varias veces.