I have an app that loads a lot of big images remotely.
When I use nostra's Universal Image Loader (https://github.com/nostra13/Android-Universal-Image-Loader) I often get Out Of Memory errors. I don't know how I should set up the imageloader to prevent this.
This is my current ImageLoader specs:
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.enableLogging()
.memoryCache(new WeakMemoryCache())
.build();
this.imgDispOpts = new DisplayImageOptions.Builder()
.cacheInMemory()
.cacheOnDisc()
.imageScaleType(ImageScaleType.IN_SAMPLE_INT)
.build();
this.imageLoader = ImageLoader.getInstance();
this.imageLoader.init(config);
And yes, I pass imgDispOpts when calling displayImage().
Try not cache in memory, use EXACTLY
scale type and RGB_565
for bitmap decoding.
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.enableLogging()
.build();
this.imgDispOpts = new DisplayImageOptions.Builder()
.cacheOnDisc()
.imageScaleType(ImageScaleType.EXACTLY)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
I tried to reduce the bitmap size in the bitmap decoder, which worked for me.
In package com.nostra13.universalimageloader.core.decode, open BaseImageDecoder.java,
public Bitmap decode(ImageDecodingInfo decodingInfo) throws IOException {
Bitmap decodedBitmap;
ImageFileInfo imageInfo;
InputStream imageStream = getImageStream(decodingInfo);
try {
imageInfo = defineImageSizeAndRotation(imageStream, decodingInfo);
imageStream = resetStream(imageStream, decodingInfo);
Options decodingOptions = prepareDecodingOptions(imageInfo.imageSize, decodingInfo);
// add in the decodingOptions here:
decodingOptions.inSampleSize = 10; // or any number
// or you can calculate the resample rate by using the screen size / grid size and the image size
decodedBitmap = BitmapFactory.decodeStream(imageStream, null, decodingOptions);
} finally {
IoUtils.closeSilently(imageStream);
}
if (decodedBitmap == null) {
L.e(ERROR_CANT_DECODE_IMAGE, decodingInfo.getImageKey());
} else {
decodedBitmap = considerExactScaleAndOrientaiton(decodedBitmap, decodingInfo, imageInfo.exif.rotation, imageInfo.exif.flipHorizontal);
}
return decodedBitmap;
}
Try the below configuration
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.enableLogging()
discCacheExtraOptions(maxImageWidthForDiscCache, maxImageHeightForDiscCache, CompressFormat.PNG, 0);
.memoryCache(new WeakMemoryCache())
.build();
this.imgDispOpts = new DisplayImageOptions.Builder()
.cacheInMemory()
.cacheOnDisc()
.imageScaleType(ImageScaleType.EXACTLY)
.build();
You can also use Lazy Loading of images.https://github.com/thest1/LazyList.
Universal Image loader based on Fedor Vlasov's project LazyList. Improved version of LazyList.
You may try this, it worked well for me:
ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context)
//Add these lines to your ImageLoader configuration
.threadPriority(Thread.NORM_PRIORITY - 2);
.denyCacheImageMultipleSizesInMemory();
.diskCacheExtraOptions(150, 150, null); // You may change image resolution to fit your needs
ImageLoader.getInstance().init(config.build());