Android通用图像加载器2图像大小与不同的网址OOM和打开文件忙

时间:2014-07-23 18:01:13

标签: android image universal-image-loader

我正在使用这个很棒的lib Universal Image Loader

问题: 当我从imge 0反复滚动到240时,我终于达到OutOfMemory异常,然后有一个位图停止加载的时刻(这发生在Galaxy tab 2 Android 4.2.2上)。

在nexus 7上尝试保存全尺寸图像时会出现异常:

java.io.FileNotFoundException: /storage/emulated/0/Android/data/com.bla.bla/cache/Folder/Full/400120282.tmp: open failed: EBUSY (Device or resource busy)
        at libcore.io.IoBridge.open(IoBridge.java:409)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:73)
        at com.nostra13.universalimageloader.cache.disc.impl.BaseDiscCache.save(BaseDiscCache.java:107)
        at com.package.workspace.uil.RememberingDiskCache.save(RememberingDiskCache.java:42)
        at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.downloadImage(LoadAndDisplayImageTask.java:291)
        at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.tryCacheImageOnDisk(LoadAndDisplayImageTask.java:273)
        at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.tryLoadBitmap(LoadAndDisplayImageTask.java:229)
        at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.run(LoadAndDisplayImageTask.java:135)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:841)

Lib version 1.9.2,来自克隆源。

Android

 <uses-sdk
    android:minSdkVersion="16"
    android:targetSdkVersion="17" />

所以我使用EcoGallery的图片加载器。 EcoGallery类似于Android Gallery,我有大约280张图片(最多)。

对于每个视图,我有2个网址: 一个缩略图约300 * 200 一个全尺寸约1920 * 2500(取决于但基本上是巨大的)

在ecoGallery中,可以同时显示1到3张图像。

规则基本上是: 显示默认的drawable 下载缩略图 显示缩略图 在此期间下载完整尺寸的img 显示完整尺寸。

使用3和完整大小为1(优先级较低)的线程池下载缩略图

为了下载拇指和完整图像,我有2个imageLoaders。

我的适配器的getView方法调用以下方法:

@Override
public void setUpImageForDownloadableImageView(final ThumbAndFullUrls urls, final ImageView imageView1) {
    if(((RememberingDiskCache) imageLoaderFull.getDiskCache()).contains(urls.imageFullUrlAsString) ){
        loadFullImage(urls.imageFullUrlAsString, imageView1, null);
    } else {
        loadThumbImage(urls.imageThumbUrlAsString, imageView1);
    }
}

以下是代码的其余部分:

ImageLoader imageLoaderThumb = ImageLoader.getInstance();
File cacheDir1 = new File(StorageUtils.getCacheDirectory(context), ALL_FOLDER_UIL);
UnlimitedDiscCache diskCache = new UnlimitedDiscCache(cacheDir1);

ImageLoaderConfiguration aDefault1 = new ImageLoaderConfiguration.Builder(context.getApplicationContext())
        .tasksProcessingOrder(QueueProcessingType.LIFO)
        .imageDownloader(new MyImageDownloader(context.getApplicationContext(), socketFactory))
        .threadPriority(Thread.NORM_PRIORITY - 2)
        .denyCacheImageMultipleSizesInMemory()
        .threadPoolSize(1) // default
        .diskCache(diskCache)
        .memoryCache(lruLimitedMemoryCache)
        .diskCacheFileNameGenerator(new HashCodeFileNameGenerator())
        .writeDebugLogs()
        .build();
imageLoaderThumb.init(aDefault1);


MyImageLoader imageLoaderFull = MyImageLoader.getInstance();
File cacheDir = new File(StorageUtils.getCacheDirectory(applicationContext), IMAGES_FOLDER_UIL);
RememberingDiskCache rememberingDiskCache = new RememberingDiskCache(cacheDir); // remembering
ImageLoaderConfiguration aDefault = new ImageLoaderConfiguration.Builder(context.getApplicationContext())
        .tasksProcessingOrder(QueueProcessingType.LIFO)
        .imageDownloader(new MyImageDownloader(context.getApplicationContext(), socketFactory))
        .threadPriority(Thread.NORM_PRIORITY - 1) // default
        .denyCacheImageMultipleSizesInMemory()
        .threadPoolSize(1) // default
        .diskCache(rememberingDiskCache)
        .memoryCache(lruLimitedMemoryCache)// full doesn't use memory cache
        .diskCacheFileNameGenerator(new HashCodeFileNameGenerator())//default
        .writeDebugLogs()
        .build();
imageLoaderFull.init(aDefault);





protected void loadThumbImage(final ThumbAndFullUrls url, final DownloadableImageView imageView1) {
    DisplayImageOptions thumbDisplayOptions = new DisplayImageOptions.Builder()
            .showImageOnLoading(defaultDrawableToShow)
            .showImageForEmptyUri(defaultDrawableToShow)
            .showImageOnFail(defaultDrawableToShow)
            .cacheInMemory(true)
            .cacheOnDisk(true)
            .imageScaleType(ImageScaleType.NONE)
            .considerExifParams(true) //fixes the weird orientation problem
            .bitmapConfig(Bitmap.Config.RGB_565)
            .build();
    imageLoaderThumb.displayImage(uri.thumbUrl,
            imageView1,
            thumbDisplayOptions,
            new ImageLoadingListener() {
                @Override public void onLoadingStarted(String imageUri, View view) {
                }

                @Override public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
                }

                @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
                    //FULL size
                    loadFullImage(url.fullSizeImageUrl, imageView1, imageView1.getDrawable());
                }

                @Override public void onLoadingCancelled(String imageUri, View view) {
                }
            });
}

protected void loadFullImage(String fullSizeImageUrl, DownloadableImageView imageView1, Drawable drawable) {
    DisplayImageOptions disaplayOptionsForFull = new DisplayImageOptions.Builder()
            .showImageOnLoading(drawable)
            .resetViewBeforeLoading(false)
            .showImageForEmptyUri(drawable)
            .showImageOnFail(drawable)
            .imageScaleType(ImageScaleType.EXACTLY)
            .cacheInMemory(false)
            .cacheOnDisk(true)
            .considerExifParams(true)
            .bitmapConfig(Bitmap.Config.RGB_565)
            .build();
    imageLoaderFull.displayImage(fullSizeImageUrl, imageView1, disaplayOptionsForFull,
            new ImageLoadingListener() {
                @Override public void onLoadingStarted(String imageUri, View view) {
                }

                @Override public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
                }

                @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
                }

                @Override public void onLoadingCancelled(String imageUri, View view) {
                }
            });
}


public class RememberingDiskCache extends UnlimitedDiscCache {

    /**
     * Remembers which uris were saved to files for quick access
     *
     * TODO: this will ignore the files that were saved in another session and doesn't actually check in the file system
     * TODO: if user deleted the files or cleared cache, we will not find out
     */
    private final ArrayList<String> filesInCache = new ArrayList<String>();

    public RememberingDiskCache(File cacheDir) {
        super(cacheDir);
    }

    public RememberingDiskCache(File cacheDir, File reserveCacheDir) {
        super(cacheDir, reserveCacheDir);
    }

    public RememberingDiskCache(File cacheDir, File reserveCacheDir, FileNameGenerator fileNameGenerator) {
        super(cacheDir, reserveCacheDir, fileNameGenerator);
    }

    @Override public boolean save(String imageUri, InputStream imageStream, IoUtils.CopyListener listener) throws IOException {
        boolean save = super.save(imageUri, imageStream, listener);
        if(save){
            addToArray(imageUri);
        }
        return save;
    }

    protected void addToArray(String imageUri) {
        if(!filesInCache.contains(imageUri)){
            filesInCache.add(imageUri);
        }
    }

    @Override public boolean save(String imageUri, Bitmap bitmap) throws IOException {
        boolean save = super.save(imageUri, bitmap);
        if(save){
            addToArray(imageUri);
        }
        return save;
    }

    @Override public boolean remove(String imageUri) {
        boolean remove = super.remove(imageUri);
        if(remove){
            filesInCache.remove(imageUri);
        }
        return remove;
    }

    @Override public void clear() {
        super.clear();
        filesInCache.clear();
    }

    public boolean contains(String imageUri){
        return filesInCache.contains(imageUri);
    }

    public class MyImageLoader extends ImageLoader {

        private volatile static MyImageLoader instance;

        /** Returns singleton class instance */
        public static MyImageLoader getInstance() {
            if (instance == null) {
                synchronized (ImageLoader.class) {
                    if (instance == null) {
                        instance = new MyImageLoader();
                    }
                }
            }
            return instance;
        }
    }

    public class MyImageDownloader extends BaseImageDownloader {
        private final SSLSocketFactory sslSocketFactory;

        public MyImageDownloader(Context context, SSLSocketFactory sslSocketFactory) {
            super(context);
            this.sslSocketFactory = sslSocketFactory;
        }

        @Override public InputStream getStream(String imageUri, Object extra) throws IOException {
            switch (Scheme.ofUri(imageUri)) {
                case HTTPS:
                    return getStreamFromNetwork(imageUri, sslSocketFactory);
                default:
                    return super.getStream(imageUri, extra);
            }
        }

        protected InputStream getStreamFromNetwork(String imageUri, SSLSocketFactory factory) throws IOException {
            HttpsURLConnection conn = createConnection(imageUri, factory);

            int redirectCount = 0;
            while (conn.getResponseCode() / 100 == 3 && redirectCount < MAX_REDIRECT_COUNT) {
                conn = createConnection(conn.getHeaderField("Location"), factory);
                redirectCount++;
            }

            InputStream imageStream;
            try {
                imageStream = conn.getInputStream();
            } catch (IOException e) {
                // Read all data to allow reuse connection (http://bit.ly/1ad35PY)
                IoUtils.readAndCloseStream(conn.getErrorStream());
                throw e;
            }
            return new ContentLengthInputStream(new BufferedInputStream(imageStream, BUFFER_SIZE), conn.getContentLength());
        }

        protected HttpsURLConnection createConnection(String url, SSLSocketFactory socketFactory) throws IOException {
            String encodedUrl = Uri.encode(url, ALLOWED_URI_CHARS);
            URL url1 = new URL(encodedUrl);
            URLConnection urlConnection = url1.openConnection();
            HttpsURLConnection conn = (HttpsURLConnection) urlConnection;
            if(socketFactory!=null){
                conn.setSSLSocketFactory(socketFactory);
            }
            conn.setHostnameVerifier(new MyHostNameVerifier(new ThreadChecker()));
            conn.setConnectTimeout(connectTimeout);
            conn.setReadTimeout(readTimeout);
            return conn;
        }
    }
}

有什么建议吗? 我想知道是否可以同时使用2个装载机,是吗?

0 个答案:

没有答案