2010-05-20 10 views
13

Tengo un ListView con ArrayAdapter personalizado. Cada una de la fila en este ListView tiene un icono y texto. Estos iconos se descargan en segundo plano, se almacenan en caché y luego usan una devolución de llamada, que se sustituye en sus respectivos ImageViews. La lógica para obtener una miniatura de la memoria caché o descarga se activa cada vez que se ejecuta getView().La mejor manera de manejar múltiples llamadas a getView desde un adaptador

Ahora, de acuerdo con Romain Guy:

"no hay absolutamente ninguna garantía sobre el orden en que getView() será llamada ni cuántas veces."

¡He visto esto suceder, para una fila del tamaño dos getView() se llamaba seis veces!

¿Cómo cambio mi código para evitar solicitudes de búsqueda de miniaturas duplicadas y también manejo el reciclaje de vistas?

Gracias.

Respuesta

8

De api.

public abstract View getView (int position, View convertView, 
           ViewGroup parent) 

convertView - La vista anterior para reutilizar, si es posible. Nota: debe verificar que esta vista no sea nula y de un tipo apropiado antes de usarla. Si no es posible convertir esta vista para mostrar los datos correctos, este método puede crear una nueva vista.

Así que si ya se ha llamado a getView para este índice específico, convertView será el objeto View que se devolvió de esa primera llamada.

Puedes hacer algo como esto.

if(!(convertView instanceof ImageView)){ 
    convertView = new ImageView(); 
    //get image from whereever 
} else {} // ImageView already created 
+0

i si escribo esto antes de cada carga de imagen, obtengo y lista vacía – FilipLuch

0

La mejor sería crear un objeto con miniatura (mapa de bits) y el texto. Y lea la miniatura si no está disponible en el objeto.

0

Cree una matriz de objetos ImageView en su adaptador y almacénelos en caché a medida que los recupera (ya sea desde caché o web). Por ejemplo, en getView, antes de recuperar el ImageView, verifique si ya está en su matriz local; de ser así, úselo, si no es necesario, una vez que se haya recibido el almacenamiento en su matriz local de ImageView para usarlo en el futuro.

14

Exactamente, eso podría suceder, por ejemplo, cuando se tiene

android:layout_height="wrap_content" 

en su definición ListView. Cambiarlo a fill_parent/match_parent lo evitaría.

+1

No desaloja completamente el problema de llamada redundante; pero ayuda a medir mejor la altura de ListView. Y si la altura se mide correctamente, ListView puede determinar correctamente el número de filas actualmente visibles que podrían reducir el número de llamadas getView() redundantes. – Samuh

+0

Esto me ayudó, incluso con ListView horizontal, cambiando el ancho en lugar de la altura. – vantesllar

+0

esta fue la respuesta para mí ... muchas gracias por el tiempo ahorrado – user2302510

1

Estoy experimentando el mismo problema que cambio el layout_height de listView to match_parent resolver mi problema.

1

Según tengo entendido, debe usar el patrón de diseño ViewHolder aquí. El solo uso de una convertView devuelta puede llevar a la reutilización de una vista previa (con alguna otra imagen asignada en este caso).

public class ImageAdapter extends ArrayAdapter<String> { 

    // Image adapter code goes here. 

    private ViewHolder { 
    public ImageView imageView; 
    public String url; 
    } 

    @Override 
    public View getView(final int position, View convertView, ViewGroup parent) { 
    View view = null; 
    ViewHolder viewHolder; 
    String url = getUrl(position); 
    if (convertView == null) { 
     // There was no view to recycle. Create a new view. 
     view = inflator.inflate(R.layout.image_layout, parent, false); 
     viewHolder = new ViewHolder(); 
     viewHolder.imageView = (ImageView) view.findViewById(R.id.image_view); 
     viewHolder.url = url; 
     view.setTag(viewHolder); 
    } else { 
     // We got a view that can be recycled. 
     view = convertView; 
     viewHolder = ((ViewHolder) view.getTag()); 
     if (viewHolder.url.equals(url)) { 
      // Nothing to do, we have the view with the correct info already. 
      return view; 
     } 
    } 

    // Do work to set your imageView which can be accessed by viewHolder.imageView 

    return view; 
    } 
} 
0

Mi fragment.xml tiene un ListView, la configuración de la presentación de esta ListView era androide: layout_height = "wrap_content", y esto ListView se unirá a SimpleCursorAdapter más tarde. Luego tengo el mismo problema en ViewBinder ser llamado 3 veces.El problema se resolvió después de cambiar el layout_height = "wrap_content" por "95p". Considero que la altura "wrap_content" causa este problema. Intentando modificar su Fragment.xml y supongo que el problema llamado 3 veces ya no existirá.

Cuestiones relacionadas