2013-05-08 52 views
7

我正在嘗試將通用映像加載程序集成到我的Android應用程序中。它有一個GridView並顯示從互聯網獲取的圖像。 我使用ArrayAdapter實現它,它以通常的方式在getView()中加載圖像。通用映像加載程序高速緩存

在正確顯示圖片方面效果很好。 但是我發現從內存緩存加載圖像時出現意外的行爲。

  1. 當活動啓動時,如果存在,UIL從互聯網或光盤緩存中加載圖像。 (當然,這是預期的行爲。)
  2. 向下滾動GridView,直到第一列從屏幕出來,然後回滾到頂部。 此時,第一列的圖像將從光盤緩存中加載,而不是內存緩存。
  3. 然後再次向下滾動。 此時,第一列的圖像從內存緩存中加載。

我希望圖像在第二次顯示時從內存緩存中加載,這是上面操作中的第2步。 我不知道爲什麼在這種情況下使用光盤緩存。

這是我的代碼。

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()在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; 

佈局XML爲在GridView的

的元件

UIL的版本是1.8.4。 經過測試的Android版本是4.1.2。

當使用上述操作將圖像加載三次時,添加UIL的日誌輸出。

// 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] 

謝謝。

回答

10

這是因爲UIL的邏輯。

1)ImageView的第一次(ImageLoader.displayImage(...))大小未知,因爲它尚未在屏幕上繪製。因此,UIL將ImageView的大小視爲全屏大小,將圖像解碼爲此大小的位圖(1080x1776,考慮寬高比)並將此位圖緩存在內存中。

2)第二次繪製ImageView的實際大小是已知的(它小於全屏大小)和UIL搜索適當大小的緩存位圖,但緩存僅包含以前大的位圖,這對我們的需要來說太大了。因此,UIL將圖像再次解碼爲更小的位圖並將其緩存在內存中。

3)以下顯示使用已經緩存的所需大小的位圖。

所以這只是UIL的一個功能。我建議您在配置中使用denyCacheImageMultipleSizesInMemory()以節省內存。

+0

感謝您的回覆。 我明白。 沒有辦法在要加載的不同大小的圖像之間共享相同的內存緩存,對嗎? 如果是這樣,我會考慮其他解決方案。 謝謝。 – KSJ 2013-05-18 05:02:43

+0

我不太明白你是什麼意思「共享不同大小的圖像之間的相同的內存緩存將被加載」。 – NOSTRA 2013-05-19 08:51:05

+0

我的意思是我希望UIL從以前緩存的內存緩存中加載圖像,即使目標尺寸不同。 – KSJ 2013-05-19 11:37:02

0

NOSTRA的答案是正確的,爲了避免這種情況(第二次請求圖像時從磁盤緩存中加載),您可以讓UIL在解碼圖像之前知道ImageView的寬度/高度,只需添加「android:maxWidth android:maxHeight 「到ImageView