Cómo cargar imágenes de forma diferida en ListView en Android

Resuelto lostInTransit asked hace 54 años • 41 respuestas

Estoy usando a ListViewpara mostrar algunas imágenes y títulos asociados con esas imágenes. Las imágenes las estoy obteniendo de Internet. ¿Hay alguna forma de cargar imágenes de forma diferida para que, mientras se muestra el texto, la interfaz de usuario no se bloquee y las imágenes se muestren a medida que se descargan?

El número total de imágenes no es fijo.

lostInTransit avatar Jan 01 '70 08:01 lostInTransit
Aceptado

Esto es lo que creé para contener las imágenes que mi aplicación muestra actualmente. Tenga en cuenta que el objeto "Registro" que se utiliza aquí es mi contenedor personalizado para la clase Log final dentro de Android.

package com.wilson.android.library;

/*
 Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/
import java.io.IOException;

public class DrawableManager {
    private final Map<String, Drawable> drawableMap;

    public DrawableManager() {
        drawableMap = new HashMap<String, Drawable>();
    }

    public Drawable fetchDrawable(String urlString) {
        if (drawableMap.containsKey(urlString)) {
            return drawableMap.get(urlString);
        }

        Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
        try {
            InputStream is = fetch(urlString);
            Drawable drawable = Drawable.createFromStream(is, "src");


            if (drawable != null) {
                drawableMap.put(urlString, drawable);
                Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "
                        + drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "
                        + drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());
            } else {
              Log.w(this.getClass().getSimpleName(), "could not get thumbnail");
            }

            return drawable;
        } catch (MalformedURLException e) {
            Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
            return null;
        } catch (IOException e) {
            Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
            return null;
        }
    }

    public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
        if (drawableMap.containsKey(urlString)) {
            imageView.setImageDrawable(drawableMap.get(urlString));
        }

        final Handler handler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message message) {
                imageView.setImageDrawable((Drawable) message.obj);
            }
        };

        Thread thread = new Thread() {
            @Override
            public void run() {
                //TODO : set imageView to a "pending" image
                Drawable drawable = fetchDrawable(urlString);
                Message message = handler.obtainMessage(1, drawable);
                handler.sendMessage(message);
            }
        };
        thread.start();
    }

    private InputStream fetch(String urlString) throws MalformedURLException, IOException {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpGet request = new HttpGet(urlString);
        HttpResponse response = httpClient.execute(request);
        return response.getEntity().getContent();
    }
}
James A Wilson avatar Feb 18 '2009 03:02 James A Wilson

Hice una demostración simple de una lista diferida (ubicada en GitHub) con imágenes.

Uso básico

ImageLoader imageLoader=new ImageLoader(context); ...
imageLoader.DisplayImage(url, imageView); 

No olvide agregar los siguientes permisos a su AndroidManifest.xml:

 <uses-permission android:name="android.permission.INTERNET"/>
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> Please

cree solo una instancia de ImageLoader y reutilícela en toda su aplicación. De esta forma el almacenamiento en caché de imágenes será mucho más eficiente.

Puede que a alguien le resulte útil. Descarga imágenes en el hilo de fondo. Las imágenes se almacenan en caché en una tarjeta SD y en la memoria. La implementación del caché es muy simple y es suficiente para la demostración. Descifro imágenes con inSampleSize para reducir el consumo de memoria. También trato de manejar correctamente las vistas recicladas.

texto alternativo

Fedor avatar Jun 18 '2010 08:06 Fedor

Recomiendo el instrumento de código abierto Universal Image Loader . Se basó originalmente en el proyecto LazyList de Fedor Vlasov y ha sido mejorado enormemente desde entonces.

  • Carga de imágenes multiproceso
  • Posibilidad de ajustar ampliamente la configuración de ImageLoader (ejecutores de subprocesos, descargador, decodificador, memoria caché de disco y memoria, opciones de visualización de imágenes y otros)
  • Posibilidad de almacenamiento en caché de imágenes en memoria y/o en el sistema de archivos del dispositivo (o tarjeta SD)
  • Posibilidad de "escuchar" el proceso de carga.
  • Posibilidad de personalizar cada llamada de imagen de visualización con opciones separadas
  • Soporte de widgets
  • Soporte para Android 2.0+

nostra13 avatar Dec 19 '2011 13:12 nostra13