2013-05-08 18 views
7

Tôi đang cố gắng tích hợp Trình tải hình ảnh phổ dụng vào Ứng dụng Android của mình. Nó có một GridView và hiển thị hình ảnh thu được từ internet. Tôi đã triển khai nó bằng cách sử dụng ArrayAdapter để tải hình ảnh trong getView() theo cách thông thường.Bộ nhớ cache tải hình ảnh phổ dụng

Nó hoạt động tốt về mặt hiển thị hình ảnh chính xác. Nhưng tôi đã tìm thấy một hành vi không mong muốn trong việc tải hình ảnh từ bộ nhớ cache.

  1. Khi hoạt động được khởi chạy, UIL tải hình ảnh từ internet hoặc bộ nhớ cache nếu có. (Tất nhiên, đó là hành vi mong đợi.)
  2. Cuộn xuống GridView cho đến khi cột đầu tiên thoát ra khỏi màn hình và cuộn về phía trên cùng. Trong thời gian này, hình ảnh ở cột đầu tiên được tải từ bộ đệm đĩa, thay vì bộ nhớ cache.
  3. Sau đó cuộn xuống và lên lại. Trong thời gian này, hình ảnh ở cột đầu tiên được tải từ bộ nhớ cache.

Tôi mong đợi hình ảnh được tải từ bộ nhớ cache ở lần hiển thị thứ hai, là bước 2 đang hoạt động ở trên. Tôi không biết tại sao bộ nhớ cache đĩa được sử dụng trong trường hợp này.

Đây là mã của tôi.

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() trong 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 cho một phần tử trong 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> 

Phiên bản UIL là 1.8.4. Phiên bản Android được kiểm tra là 4.1.2.

Đã thêm đầu ra bản ghi của UIL khi một hình ảnh được tải ba lần với một thao tác được mô tả ở trên.

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

Cảm ơn bạn.

Trả lời

10

Điều này là do logic của UIL.

1) Lần đầu tiên (ImageLoader.displayImage(...)) kích thước của ImageView không xác định do chưa được vẽ trên màn hình. Vì vậy, UIL coi kích thước của ImageView là kích thước toàn màn hình, giải mã hình ảnh thành Bitmap có kích thước này (1080x1776, xem xét tỷ lệ khung hình) và lưu trữ Bitmap này trong bộ nhớ.

2) Kích thước thực của ImageView được rút ra (nhỏ hơn kích thước toàn màn hình) và tìm kiếm UIL được lưu trong bộ nhớ cache Bitmap có kích thước phù hợp nhưng bộ nhớ cache chỉ chứa Bitmap lớn trước đó. Vì vậy, UIL giải mã hình ảnh một lần nữa vào Bitmap nhỏ hơn và bộ nhớ cache nó trong bộ nhớ quá.

3) Hiển thị sau sử dụng Bitmap đã lưu trong bộ nhớ cache kích thước cần thiết.

Vì vậy, đây chỉ là một tính năng của UIL.Tôi khuyên bạn nên sử dụng cấu hình denyCacheImageMultipleSizesInMemory() để lưu bộ nhớ.

+0

cảm ơn bạn đã trả lời. Tôi hiểu. Không có cách nào để chia sẻ cùng một bộ nhớ cache giữa các hình ảnh ở kích thước khác nhau sẽ được tải, phải không? Nếu có, tôi sẽ xem xét các giải pháp khác. Cảm ơn bạn. – KSJ

+0

Tôi không hoàn toàn hiểu ý của bạn bằng cách "chia sẻ cùng một bộ nhớ đệm giữa các ảnh ở kích thước khác nhau để được tải". – NOSTRA

+0

Tôi có nghĩa là tôi muốn tải UIL hình ảnh từ bộ nhớ cache đã được lưu trữ trước đó ngay cả khi kích thước mục tiêu khác nhau. – KSJ

0

Câu trả lời của NOSTRA là đúng, để tránh điều này (tải từ bộ đệm đĩa khi lần thứ hai yêu cầu hình ảnh), bạn có thể cho UIL biết chiều rộng/chiều cao của ImageView trước khi mã hóa hình ảnh, chỉ cần thêm "android: maxWidth android: maxHeight "tới ImageView