android - 使用UniversalImageLoader将Bitmaps加载到ArrayList时延迟

时间:2015-08-02 22:50:52

标签: android arraylist bitmap delay universal-image-loader

我需要将Bitmaps加载到ArrayList中,然后将其转换为Bitmap []并传递给ArrayAdapter以扩充ListView。我使用UniversalImageLoader库,这是我的代码:

final ArrayList<Bitmap> imgArray = new ArrayList<>(); //before the method scope, as a class field
//...some code...
File cacheDir = StorageUtils.getOwnCacheDirectory(
            getApplicationContext(),
            "/sdcard/Android/data/random_folder_for_cache");

    DisplayImageOptions options = new DisplayImageOptions.Builder()
            .cacheInMemory(true).cacheOnDisc(true).build();

    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
            getApplicationContext()).defaultDisplayImageOptions(options)
            //.discCache(new FileCounterLimitedCache(cacheDir, 100)) - I commented it 'cause FileCounterLimitedCache isn't recognized for some reason
            .build();
    ImageLoader.getInstance().init(config);

    for (int num=0;num<4;num++) {
        ImageLoader imageLoader = ImageLoader.getInstance();
        final int constNum = num;
        imageLoader.loadImage("http://example.com/sample.jpg", new SimpleImageLoadingListener()
        {
            @Override
            public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage)
            {
                imgArray.add(constNum, loadedImage);
            }
        });
    }

但我有一些问题需要努力。首先,它在第一次运行时经常返回错误(IndexOutOfBoundsException - 当前索引超过ArrsyList的大小)。然后在一段时间(大约一分钟)之后,ArrayList的大小为1(我用Toast检查),然后当立即再次运行时,它已经是4(因为它需要)。奇怪。但是我需要首先填充ArrayList,然后完成所有其他操作(它们会被延迟并且我在第一次运行时没有错误)。怎么做?

如果有人没有SD卡怎么办?顺便说一下,我无法在SD上找到创建的缓存文件夹......

3 个答案:

答案 0 :(得分:0)

您无法按照您尝试的方式添加元素。例如,如果第二张图片首先完成加载,则代码会正确抛出IndexOutOfBoundsException,因为您尝试添加的位置超出当前大小 - 请参阅the documentation

你可能最好使用一个数组初始化为元素数量,因为你知道它的4个元素 - 例如

final Bitmap[] imgArray = new Bitmap[4];

然后使用

添加onLoadingComplete()中的元素
imgArray[constNum] = loadedImage;

答案 1 :(得分:0)

您可以使用SparseArray代替ArrayList来避免使用IndexOutOfBoundsException。 我认为这就是你所追求的:

final SparseArray<Bitmap> imgArray = new SparseArray<>(); //before the method scope, as a class field
int numberOfImages;
int numberOfLoadedImages;

//...some code...
File cacheDir = StorageUtils.getOwnCacheDirectory(
        getApplicationContext(),
        "/sdcard/Android/data/random_folder_for_cache");

DisplayImageOptions options = new DisplayImageOptions.Builder()
        .cacheInMemory(true).cacheOnDisc(true).build();

ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
        getApplicationContext()).defaultDisplayImageOptions(options)
        //.discCache(new FileCounterLimitedCache(cacheDir, 100)) - I commented it 'cause FileCounterLimitedCache isn't recognized for some reason
        .build();
ImageLoader.getInstance().init(config);

numberOfImages = 4;
numberOfLoadedImages = 0;

for (int num=0;num<4;num++) {
    ImageLoader imageLoader = ImageLoader.getInstance();
    final int constNum = num;
    imageLoader.loadImage("http://example.com/sample.jpg", new SimpleImageLoadingListener()
    {
        @Override
        public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage)
        {
            imgArray.put(constNum, loadedImage);
            numberOfLoadedImages++;
            if(numberOfImages == numberOfLoadedImages)
            {
                //Do all the other actions
            }
        }
    });
}

答案 2 :(得分:0)

Universal Image Loader库包含以下方法:

public void displayImage(java.lang.String uri, android.widget.ImageView imageView)

可以传递图片网址和ImageView以在其上显示图片。 加上那个,如果以后相同的ImageView传递给方法,但使用不同的网址,可能会发生两件事:

  
      
  1. 如果已经下载旧图像,通常新图像将被设置为ImageView。

  2.   
  3. 如果仍在下载库的旧图像将取消正在下载旧图像的http连接。并开始下载   新形象。 (可以在LogCat中观察到)。这种行为发生了   使用适配器时。

  4.   

方法调用:

ImageLoader.getInstance().displayImage("http://hydra-media.cursecdn.com/dota2.gamepedia.com/b/bd/Earthshaker.png", imageView1);

<强>配置:

如果未指定defaultDisplayImageOptions,则缓存将不起作用。告诉图书馆在哪里保存这些图像。因为这个库有从Assets,Drawables或Internet加载图像的选项:

DisplayImageOptions opts = new DisplayImageOptions.Builder().cacheInMemory(true).cacheOnDisk(true).build();
  

使用此选项,图像将保存在应用程序中。内部存储器。   不要担心设备是否有外部存储器。

ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this)
                .defaultDisplayImageOptions(opts)
                .memoryCache(new LruMemoryCache(2 * 1024 * 1024))
                .memoryCacheSize(2 * 1024 * 1024)
                .diskCacheSize(50 * 1024 * 1024)
                .diskCacheFileCount(100)
                .writeDebugLogs()
                .build();

ImageLoader.getInstance().init(config);

I created a working github repository for it. check it out.