I'm trying to integrate Universal Image Loader into my Android App. It has a GridView and shows images acquired from internet. I implemented it using ArrayAdapter which loads images in getView() in a usual way.
It works well in terms of displaying picture correctly. But I found an unexpected behavior in loading images from memory cache.
I expect images are loaded from memory cache at second time of displaying, which is step 2 in operation above. I don't know why disc cache is used in this case.
Here is my codes.
ImageLoaderConfiguration
ImageLoaderConfiguration mImageLoaderConfig =
new ImageLoaderConfiguration.Builder(getApplicationContext())
.defaultDisplayImageOptions(defaultOptions)
.enableLogging()
.build();
DisplayImageOptions
DisplayImageOptions defaultOptions =
new DisplayImageOptions.Builder()
.cacheInMemory()
.cacheOnDisc()
.showImageForEmptyUri(R.drawable.empty_photo)
.showStubImage(R.drawable.empty_photo)
.displayer(new FadeInBitmapDisplayer(500))
.build();
getView() in ArrayAdapter
if (convertView == null) {
convertView = (FrameLayout) LayoutInflater.from(getContext())
.inflate(mLayoutId, null);
convertView.setLayoutParams(mImageViewLayoutParams);
} else { // Otherwise re-use the converted view
convertView.findViewById(R.id.videoIconInThumbnail).setVisibility(View.GONE);
}
// Check the height matches our calculated column width
if (convertView.getLayoutParams().height != mItemHeight) {
convertView.setLayoutParams(mImageViewLayoutParams);
}
ImageView image = (ImageView) convertView.findViewById(R.id.photoThumbnail);
ImageLoader.getInstance().displayImage(thumbnailUrl, image,
new SimpleImageLoadingListener() {
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
Log.v(TAG, imageUri + " is loaded.");
}
});
return convertView;
layout XML for an element in GridView
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@+id/photoThumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" >
</ImageView>
<ImageView
android:id="@+id/videoIconInThumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_play"
android:visibility="gone" >
</ImageView>
</FrameLayout>
Version of UIL is 1.8.4. Tested Android version is 4.1.2.
Added log output of UIL when an image is loaded for three times with a operation described above.
// Fist time of displaying
I/ImageLoader( 7404): Start display image task [http://xxx/yyy.JPG_1080x1776]
I/ImageLoader( 7404): Load image from disc cache [http://xxx/yyy.JPG_1080x1776]
I/ImageLoader( 7404): Subsample original image (x192) to x192 (scale = 1) [http://xxx/yyy.JPG_1080x1776]
I/ImageLoader( 7404): Cache image in memory [http://xxx/yyy.JPG_1080x1776]
I/ImageLoader( 7404): Display image in ImageView [http://xxx/yyy.JPG_1080x1776]
// Second time of displaying
I/ImageLoader( 7404): ImageLoader is paused. Waiting... [http://xxx/yyy.JPG_358x357]
I/ImageLoader( 7404): Start display image task [http://xxx/yyy.JPG_358x357]
I/ImageLoader( 7404): Load image from disc cache [http://xxx/yyy.JPG_358x357]
I/ImageLoader( 7404): Subsample original image (x192) to x192 (scale = 1) [http://xxx/yyy.JPG_358x357]
I/ImageLoader( 7404): Cache image in memory [http://xxx/yyy.JPG_358x357]
I/ImageLoader( 7404): Display image in ImageView [http://xxx/yyy.JPG_358x357]
// Third time of displaying
I/ImageLoader( 7404): Load image from memory cache [http://xxx/yyy.JPG_358x357]
Thank you.
This is because of UIL's logic.
1) First time (ImageLoader.displayImage(...)
) size of ImageView is unknown because it haven't drawn yet on screen. So UIL considers size of ImageView as full screen size, decodes image to Bitmap of this size (1080x1776, considering aspect ratio) and caches this Bitmap in memory.
2) Second time real size of drawn ImageView is known (which is smaller than full screen size) and UIL search cached Bitmap of appropriate size but cache contains only previous large Bitmap which is too large for our needs. So UIL decodes image again into smaller Bitmap and cache it in memory too.
3) Following displays uses already cached Bitmap of needed size.
So this is just a feature of UIL. I recommend you to use denyCacheImageMultipleSizesInMemory()
in configuration to save memory.