0

我的应用程序中有一个 ListView,ListView 的项目将显示图像。所以我需要异步加载器从 Http 加载图像。

现在我用谷歌的Bitmapfun,但你知道,它很复杂,至少我是这么认为的。

所以我想重新编码,遇到一个问题。

如何从 Http 下载相同的 Url 图片并且不重复 httpRequest 和异步执行?

因为在ListView的item中,可能显示的是同一张图片。在Bitmapfun,google“同步”了进程,所以下载图片无法并发。</p>

帮我!想一想T_T

.........对不起,英语不好。

一个 ListView,例如,有 5 个项目。每个项目都有一个 ImageView 来显示图像。我使用 AsyncTask 发出 Http 请求,下载它,放入缓存,并显示它。

可能是五个图像是

"hxxp://xxx.com/1.jpg",

"hxxp://xxx.com/2.jpg",

"hxxp://xxx.com/3.jpg",

"hxxp://xxx.com/1.jpg",

"hxxp://xxx.com/1.jpg"

所以这三个Http请求是一样的。但是 AsyncTask 是同时工作的。所以另外两个Http请求被重复了。

我要解决的问题是“如何为 AsyncTask 下载图像但如果相同的 Url 只下载一次?”.....

编辑: 使用惰性列表:

 private Bitmap getBitmap(String url) 
{
    File f=fileCache.getFile(url);

    //from SD cache
    Bitmap b = decodeFile(f);
    if(b!=null){
        Log.d("ImageLoader", " From Cache" + url);
        return b;
    }
    //from web
    try {
        Log.d("ImageLoader", " Begin Downloading" + url);
        Bitmap bitmap=null;
        URL imageUrl = new URL(url);
        HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
        conn.setConnectTimeout(30000);
        conn.setReadTimeout(30000);
        conn.setInstanceFollowRedirects(true);
        InputStream is=conn.getInputStream();
        OutputStream os = new FileOutputStream(f);
        Utils.CopyStream(is, os);
        os.close();
        conn.disconnect();
        bitmap = decodeFile(f);
        return bitmap;
    } catch (Throwable ex){
       ex.printStackTrace();
       if(ex instanceof OutOfMemoryError)
           memoryCache.clear();
       return null;
    }
}

初始化 ListView 和日志是:

04-09 10:44:31.900: D/ImageLoader(8578): 开始下载 hxxps://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg 04-09 10:44 :31.910: D/ImageLoader(8578): 开始下载 hxxps://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg 04-09 10:44:31.910: D/ImageLoader (8578): 开始下载 hxxps://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg 04-09 10:44:31.910: D/ImageLoader(8578): 开始下载hxxps://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg 04-09 10:44:31.930: D/ImageLoader(8578): 开始下载 hxxps://lh6.谷歌用户内容。com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg 04-09 10:44:33.090:I/MemoryCache(8578):缓存大小=44032 长度=1 04-09 10:44:33.090: D/ImageLoader(8578):开始下载 hxxps://lh6.googleusercontent.com/-UBmLbPELvoQ/URqucCdv0kI/AAAAAAAAAbs/IdNhr2VQoQs/s1024/Apre%2525CC%252580s%252520la%252520Pluie.jpg 04-09 10:44:33.140: I/MemoryCache(8578): 缓存大小=44032 长度=1 04-09 10:44:33.140: D/ImageLoader(8578): 开始下载 hxxps://lh6.googleusercontent.com/-UBmLbPELvoQ/URqucCdv0kI/AAAAAAAAAbs/IdNhr2VQoQs /s1024/Apre%2525CC%252580s%252520la%252520Pluie.jpgcom/-UBmLbPELvoQ/URqucCdv0kI/AAAAAAAAAbs/IdNhr2VQoQs/s1024/Apre%2525CC%252580s%252520la%252520Pluie.jpg 04-09 10:44:33.140: I/MemoryCache(8578): 缓存大小=44032 长度=1 04 10:44:33.140: D/ImageLoader(8578): 开始下载 hxxps://lh6.googleusercontent.com/-UBmLbPELvoQ/URqucCdv0kI/AAAAAAAAAbs/IdNhr2VQoQs/s1024/Apre%2525CC%252580s%252520la%252520Pluie.jpgcom/-UBmLbPELvoQ/URqucCdv0kI/AAAAAAAAAbs/IdNhr2VQoQs/s1024/Apre%2525CC%252580s%252520la%252520Pluie.jpg 04-09 10:44:33.140: I/MemoryCache(8578): 缓存大小=44032 长度=1 04 10:44:33.140: D/ImageLoader(8578): 开始下载 hxxps://lh6.googleusercontent.com/-UBmLbPELvoQ/URqucCdv0kI/AAAAAAAAAbs/IdNhr2VQoQs/s1024/Apre%2525CC%252580s%252520la%252520Pluie.jpg

使用https://github.com/nostra13/Android-Universal-Image-Loader

if (bmp != null && !bmp.isRecycled()) {
        Log.d("ImageLoader", " From Cache " + uri);
        if (configuration.loggingEnabled)
            L.i(LOG_LOAD_IMAGE_FROM_MEMORY_CACHE, memoryCacheKey);

        if (options.shouldPostProcess()) {
            ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageView, targetSize, options, listener,
                    engine.getLockForUri(uri));
            ProcessAndDisplayImageTask displayTask = new ProcessAndDisplayImageTask(engine, bmp, imageLoadingInfo, options.getHandler());
            engine.submit(displayTask);
        } else {
            options.getDisplayer().display(bmp, imageView);
            listener.onLoadingComplete(uri, imageView, bmp);
        }
    } else {
        Log.d("ImageLoader", " Begin Downloading " + uri);
        if (options.shouldShowStubImage()) {
            imageView.setImageResource(options.getStubImage());
        } else {
            if (options.isResetViewBeforeLoading()) {
                imageView.setImageBitmap(null);
            }
        }

        ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageView, targetSize, options, listener,
                engine.getLockForUri(uri));
        LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(engine, imageLoadingInfo, options.getHandler());
        engine.submit(displayTask);
    }

初始化 ListView 和日志是:

04-09 10:23:24.590: D/ImageLoader(7336): 开始下载 hxxps://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg 04-09 10:23 :24.600: D/ImageLoader(7336): 开始下载 hxxps://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg 04-09 10:23:24.600: D/ImageLoader (7336): 开始下载 hxxps://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg 04-09 10:23:24.610: D/ImageLoader(7336): 开始下载hxxps://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg 04-09 10:23:24.610: D/ImageLoader(7336): 开始下载 hxxps://lh6.谷歌用户内容。com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg 04-09 10:23:24.610:D/ImageLoader(7336):开始下载 hxxps://lh6.googleusercontent.com/-UBmLbPELvoQ/URqucCdv0I /AAAAAAAAAbs/IdNhr2VQoQs/s1024/Apre%2525CC%252580s%252520la%252520Pluie.jpg 04-09 10:23:24.610:D/ImageLoader(7336):开始下载 hxxps://lh6.googleusercontent.com/-UBmLbPELvoQ/URqucCdv0Ik /AAAAAAAAAbs/IdNhr2VQoQs/s1024/Apre%2525CC%252580s%252520la%252520Pluie.jpgcom/-UBmLbPELvoQ/URqucCdv0kI/AAAAAAAAAbs/IdNhr2VQoQs/s1024/Apre%2525CC%252580s%252520la%252520Pluie.jpgcom/-UBmLbPELvoQ/URqucCdv0kI/AAAAAAAAAbs/IdNhr2VQoQs/s1024/Apre%2525CC%252580s%252520la%252520Pluie.jpg

所以 httpRequest 是 Repeat....

4

1 回答 1

0

您可以使用延迟加载或通用图像加载器

延迟列表是使用 url 从 sdcard 或 fomr 服务器延迟加载图像。这就像按需加载图像。

图像可以缓存到本地sd卡或手机内存。Url 被认为是关键。如果密钥存在于 sdcard 中,则显示来自 sd 卡的图像,否则通过从服务器下载显示图像并将其缓存到您选择的位置。可以设置缓存限制。您还可以选择自己的位置来缓存图像。缓存也可以清除。

而不是用户等待下载大图像然后显示惰性列表按需加载图像。由于图像区域缓存,您可以离线显示图像。

https://github.com/thest1/LazyList。懒惰列表

在你的 getview

imageLoader.DisplayImage(imageurl, imageview); ImageLoader 显示方法

public void DisplayImage(String url, ImageView imageView) //url and imageview as parameters
{
imageViews.put(imageView, url);
Bitmap bitmap=memoryCache.get(url);   //get image from cache using url as key
if(bitmap!=null)         //if image exists
    imageView.setImageBitmap(bitmap);  //dispaly iamge
 else   //downlaod image and dispaly. add to cache.
 {
    queuePhoto(url, imageView);
    imageView.setImageResource(stub_id);
 }

惰性列表的替代方法是通用图像加载器

https://github.com/nostra13/Android-Universal-Image-Loader。它基于惰性列表(工作原理相同)。但它还有很多其他配置。我更喜欢使用Universal Image Loader,因为它为您提供了更多配置选项。如果下载失败,您可以显示错误图像。可以显示带圆角的图像。可以缓存在磁盘或内存上。可以压缩图像。

在您的自定义适配器构造函数中

 File cacheDir = StorageUtils.getOwnCacheDirectory(a, "your folder");

// Get singletone instance of ImageLoader
imageLoader = ImageLoader.getInstance();
// Create configuration for ImageLoader (all options are optional)
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(a)
      // You can pass your own memory cache implementation
     .discCache(new UnlimitedDiscCache(cacheDir)) // You can pass your own disc cache implementation
     .discCacheFileNameGenerator(new HashCodeFileNameGenerator())
     .enableLogging()
     .build();
 // Initialize ImageLoader with created configuration. Do it once.
 imageLoader.init(config);
  options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.stub_id)//display stub image
.cacheInMemory()
.cacheOnDisc()
.displayer(new RoundedBitmapDisplayer(20))
 .build();

在你的 getView()

 ImageView image=(ImageView)vi.findViewById(R.id.imageview); 
 imageLoader.displayImage(imageurl, image,options);//provide imageurl, imageview and options

您可以配置其他选项以满足您的需求。

与延迟加载/通用图像加载器一起,您可以查看持有者以实现平滑滚动和性能。http://developer.android.com/training/improving-layouts/smooth-scrolling.html

编辑:

如您所见,图像显示两次(下载一次)。但是它只被缓存一次。下面的图片是图标。我在测试时没有正确缩放它。所以看起来很拉长。

在此处输入图像描述

于 2013-04-08T09:33:16.830 回答