如何使用通用图片加载器进行离线缓存?

14

使用通用图像加载器(universal image loader)可以离线缓存吗?如果可以,如何使用?需要使用配置文件吗?如何手动设置下载目录?

加载大型图片时出现内存不足错误:

我的代码:

DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
            .cacheOnDisc(true).cacheInMemory(true)
            .imageScaleType(ImageScaleType.IN_SAMPLE_INT)
            .displayer(new FadeInBitmapDisplayer(300)).build();
    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(G.appConfigs.context)
            .defaultDisplayImageOptions(defaultOptions)
            .memoryCacheExtraOptions(480, 800) // default = device screen dimensions
            .diskCacheExtraOptions(480, 800, null)
            .memoryCache(new WeakMemoryCache())
            .memoryCache(new LruMemoryCache(2 * 1024 * 1024))
            .memoryCacheSize(2 * 1024 * 1024)
            .discCacheSize(300 * 1024 * 1024)
            .build();
    ImageLoader.getInstance().init(config);
    // END - UNIVERSAL IMAGE LOADER SETUP

    ImageLoader imageLoader = ImageLoader.getInstance();

        DisplayImageOptions options = new DisplayImageOptions.Builder().cacheInMemory(true)
            .cacheOnDisc(true).resetViewBeforeLoading(true)
            .showImageForEmptyUri(R.drawable.no_pic)
            .showImageOnFail(R.drawable.load_failed)
            .showImageOnLoading(R.drawable.img_thumb).build();

    //download and display image from url
    imageLoader.displayImage(imgURL, img, options);

如何解决它?

5个回答

15
您可以使用ImageLoaderConfiguration.Builder类来自定义磁盘缓存,其中包括以下方法:
  • diskCacheExtraOptions()
  • diskCacheSize()(以字节为单位)。
  • diskCacheFileCount()
  • diskCacheFileNameGenerator()
  • 还有其他一些方法。
或者,您可以使用diskCache(DiskCache)来提供一个自定义类来实现离线缓存。
从维基百科的配置部分示例中可以看出。
File cacheDir = StorageUtils.getCacheDirectory(context);
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
    .memoryCacheExtraOptions(480, 800) // default = device screen dimensions
    .diskCacheExtraOptions(480, 800, null)
    .taskExecutor(...)
    .taskExecutorForCachedImages(...)
    .threadPoolSize(3) // default
    .threadPriority(Thread.NORM_PRIORITY - 1) // default
    .tasksProcessingOrder(QueueProcessingType.FIFO) // default
    .denyCacheImageMultipleSizesInMemory()
    .memoryCache(new LruMemoryCache(2 * 1024 * 1024))
    .memoryCacheSize(2 * 1024 * 1024)
    .memoryCacheSizePercentage(13) // default
    .diskCache(new UnlimitedDiscCache(cacheDir)) // default
    .diskCacheSize(50 * 1024 * 1024)
    .diskCacheFileCount(100)
    .diskCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default
    .imageDownloader(new BaseImageDownloader(context)) // default
    .imageDecoder(new BaseImageDecoder()) // default
    .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default
    .writeDebugLogs()
    .build();

所以它可以离线显示图片吗?非常感谢。 - Hossein Kurd
如果我关闭应用程序然后重新启动它,它是否仍将保留缓存的图像?是否有一种方法可以使用通用图像加载器来持久化它们? - Shobhit Puri
@ShobhitPuri 这就是这个功能的目的。 - matiash
太好了!非常感谢。 - Shobhit Puri
我怎么能够获取图像本地路径? - Hossein Kurd

4

但是,如果您重新启动设备或以任何方式清除缓存,它将无法离线工作,因为缓存文件将被删除。
要显示离线图片,您需要将图片下载到 SD 卡的特定文件夹中,并在离线情况下从那里选择。


你的意思是说,如果按照@matiash提到的步骤操作,图像将在重新启动后被删除。啊!我不知道这一点。 - Shobhit Puri
1
那就意味着 Universal Image Loader 不能用于离线存储图像。你知道有哪些库可以简化这个过程吗?否则我就得使用 AsyncTask 从所有 URL 下载图像,然后将其存储在数据库或 SD 卡的某个位置。我认为使用一个库会更容易些。 - Shobhit Puri

3

我不太了解这样的库。但是,您可以使用以下方法下载图像。只需从 异步任务 中调用它并传递您的URL。

private File root = Environment.getExternalStorageDirectory();
private File dir = new File(root.getAbsolutePath() + "/ImageFolder");

private void downloadFile(String url) throws Exception {
    URL ur = new URL(url);
    String fileName = url.substring(url.lastIndexOf("/") + 1);
    File file = new File(dir, fileName);
    URLConnection uconn = ur.openConnection();
    InputStream is = uconn.getInputStream();
    BufferedInputStream bufferinstream = new BufferedInputStream(is);
    ByteArrayBuffer baf = new ByteArrayBuffer(5000);
    int current = 0;
    while ((current = bufferinstream.read()) != -1) {
        baf.append((byte) current);
    }
    FileOutputStream fos = new FileOutputStream(file);
    fos.write(baf.toByteArray());
    fos.flush();
    fos.close();
}

我想在 ListView 或 GridView 中使用它,我知道下载方法并且以前也做过,但我想使用最简单的方法来解决它。 - Hossein Kurd
你需要一个永久缓存(离线支持)吗?或者只是想要进行懒加载吗? - Nitesh

1

通用图像加载器是一个完美的库,可以异步加载您的图像。您可以使用@matiash的答案来设置库配置,然后使用

ImageLoader.getInstance().init(config);

你可以将它们应用于ImageLoader实例。之后,如果你的应用程序在开始时有互联网连接,通用图像加载器将下载并缓存你所有的图像,在你使用通用图像加载器库加载这些图像的地方。下一次加载相同的图像时,通用图像加载器将从缓存中获取它们,这意味着你不需要任何互联网连接(可以离线工作)。 问题出现在某人安装你的应用程序并尝试第一次使用它时,如果他没有互联网连接。然后通用图像加载器将尝试从Web服务器加载你的图像并将它们缓存到存储器中,但它会失败,因为你没有互联网连接。这就是为什么通用图像加载器有一个类名为DisplayImageOptions的原因:

new DisplayImageOptions.Builder()

这些方法可以让您设置在加载图像时出现问题时应该发生什么。您可以使用以下方法:

.showImageOnLoading(R.drawable.default_image)
.showImageForEmptyUri(R.drawable.default_image)
.showImageOnFail(R.drawable.default_image)

这是一个关于如何使用它的示例:

Here is an example how you can use it:

DisplayImageOptions imageOptions = new DisplayImageOptions.Builder()
    .showImageOnLoading(getImageLoaderDefaultImage())
    .showImageForEmptyUri(getImageLoaderDefaultImage())
    .showImageOnFail(getImageLoaderDefaultImage())
    .cacheInMemory(true)
    .cacheOnDisk(true)
    .considerExifParams(true)
    .build();

方法 getImageLoaderDefaultImage():

private int getImageLoaderDefaultImage(){ return R.drawable.default_img;}

当您想要加载图像时,以下是如何使用图像加载器:

ImageLoader.getInstance().displayImage("image url", myImageView,imageOptions);

0
如果您正在使用Xamarin:请在OnCreateView或类似位置添加以下代码,Java中也可用。
DisplayImageOptions options = new DisplayImageOptions.Builder().CacheInMemory(true).CacheOnDisk(true).Build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this.Context).DefaultDisplayImageOptions(options).Build();
ImageLoader.Instance.Init(config);

在加载图像时添加以下代码行。
ImageLoader imageLoader = ImageLoader.Instance;
imageLoader.DisplayImage(imgURL, imageSource);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接