1. 程式人生 > >Android-Universal-Image-Loader三大元件DisplayImageOptions、ImageLoader、ImageLoaderConfiguration詳解

Android-Universal-Image-Loader三大元件DisplayImageOptions、ImageLoader、ImageLoaderConfiguration詳解

一、介紹

 Android-Universal-Image-Loader是一個開源的UI元件程式,該專案的目的是提供一個可重複使用的儀器為非同步影象載入,快取和顯示。所以,如果你的程式裡需要這個功能的話,那麼不妨試試它。因為已經封裝好了一些類和方法。我們 可以直接拿來用了。而不用重複去寫了。其實,寫一個這方面的程式還是比較麻煩的,要考慮多執行緒快取,記憶體溢位等很多方面。

二、具體使用

一個好的類庫的重要特徵就是可配置性強。我們先簡單使用Android-Universal-Image-Loader,一般情況下使用預設配置就可以了。

下面的例項利用Android-Universal-Image-Loader將網路圖片載入到圖片牆中。

複製程式碼
 1 public class BaseActivity extends Activity {
 2     ImageLoader imageLoader;
 3     @Override
 4     protected void onCreate(Bundle savedInstanceState) {
 5           // Create global configuration and initialize ImageLoader with this configuration
 6         ImageLoaderConfiguration config = new
ImageLoaderConfiguration.Builder(getApplicationContext()) 7 .build(); 8 ImageLoader.getInstance().init(config); 9 super.onCreate(savedInstanceState); 10 } 11 }
複製程式碼 複製程式碼
  1 public class MainActivity extends BaseActivity {
  2 
  3     @Override
  4     protected void
onCreate(Bundle savedInstanceState) { 5 super.onCreate(savedInstanceState); 6 setContentView(R.layout.activity_main); 7 8 ImageLoader imageLoader = ImageLoader.getInstance(); 9 10 GridView gridView = (GridView) this.findViewById(R.id.grdvImageWall); 11 gridView.setAdapter(new PhotoWallAdapter(Constants.IMAGES)); 12 } 13 14 static class ViewHolder { 15 ImageView imageView; 16 ProgressBar progressBar; 17 } 18 19 public class PhotoWallAdapter extends BaseAdapter { 20 String[] imageUrls; 21 ImageLoader imageLoad; 22 DisplayImageOptions options; 23 LinearLayout gridViewItem; 24 25 public PhotoWallAdapter(String[] imageUrls) { 26 assert imageUrls != null; 27 this.imageUrls = imageUrls; 28 29 options = new DisplayImageOptions.Builder() 30 .showImageOnLoading(R.drawable.ic_stub) // resource or 31 // drawable 32 .showImageForEmptyUri(R.drawable.ic_empty) // resource or 33 // drawable 34 .showImageOnFail(R.drawable.ic_error) // resource or 35 // drawable 36 .resetViewBeforeLoading(false) // default 37 .delayBeforeLoading(1000).cacheInMemory(false) // default 38 .cacheOnDisk(false) // default 39 .considerExifParams(false) // default 40 .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default 41 .bitmapConfig(Bitmap.Config.ARGB_8888) // default 42 .displayer(new SimpleBitmapDisplayer()) // default 43 .handler(new Handler()) // default 44 .build(); 45 this.imageLoad = ImageLoader.getInstance(); 46 47 } 48 49 @Override 50 public int getCount() { 51 return this.imageUrls.length; 52 } 53 54 @Override 55 public Object getItem(int position) { 56 if (position <= 0 || position >= this.imageUrls.length) { 57 throw new IllegalArgumentException( 58 "position<=0||position>=this.imageUrls.length"); 59 } 60 return this.imageUrls[position]; 61 } 62 63 @Override 64 public long getItemId(int position) { 65 return position; 66 } 67 68 @Override 69 public View getView(int position, View convertView, ViewGroup parent) { 70 // 判斷這個image是否已經在快取當中,如果沒有就下載 71 final ViewHolder holder; 72 if (convertView == null) { 73 holder = new ViewHolder(); 74 gridViewItem = (LinearLayout) getLayoutInflater().inflate( 75 R.layout.image_wall_item, null); 76 holder.imageView = (ImageView) gridViewItem 77 .findViewById(R.id.item_image); 78 holder.progressBar = (ProgressBar) gridViewItem 79 .findViewById(R.id.item_process); 80 gridViewItem.setTag(holder); 81 convertView = gridViewItem; 82 } else { 83 holder = (ViewHolder) gridViewItem.getTag(); 84 } 85 this.imageLoad.displayImage(this.imageUrls[position], 86 holder.imageView, options, 87 new SimpleImageLoadingListener() { 88 89 @Override 90 public void onLoadingStarted(String imageUri, View view) { 91 holder.progressBar.setProgress(0); 92 holder.progressBar.setVisibility(View.VISIBLE); 93 } 94 95 @Override 96 public void onLoadingFailed(String imageUri, View view, 97 FailReason failReason) { 98 holder.progressBar.setVisibility(View.GONE); 99 } 100 101 @Override 102 public void onLoadingComplete(String imageUri, 103 View view, Bitmap loadedImage) { 104 holder.progressBar.setVisibility(View.GONE); 105 } 106 107 }, new ImageLoadingProgressListener() { 108 109 @Override 110 public void onProgressUpdate(String imageUri, 111 View view, int current, int total) { 112 holder.progressBar.setProgress(Math.round(100.0f 113 * current / total)); 114 } 115 }); // 通過URL判斷圖片是否已經下載 116 return convertView; 117 } 118 119 } 120 }
複製程式碼

裡面主要的物件都用 突出顯示了。

三者的關係

ImageLoaderConfiguration是針對圖片快取的全域性配置,主要有執行緒類、快取大小、磁碟大小、圖片下載與解析、日誌方面的配置。

ImageLoader是具體下載圖片,快取圖片,顯示圖片的具體執行類,它有兩個具體的方法displayImage(...)、loadImage(...),但是其實最終他們的實現都是displayImage(...)。

DisplayImageOptions用於指導每一個Imageloader根據網路圖片的狀態(空白、下載錯誤、正在下載)顯示對應的圖片,是否將快取載入到磁碟上,下載完後對圖片進行怎麼樣的處理。

從三者的協作關係上看,他們有點像廚房規定、廚師、客戶個人口味之間的關係。ImageLoaderConfiguration就像是廚房裡面的規定,每一個廚師要怎麼著裝,要怎麼保持廚房的乾淨,這是針對每一個廚師都適用的規定,而且不允許個性化改變。ImageLoader就像是具體做菜的廚師,負責具體菜譜的製作。DisplayImageOptions就像每個客戶的偏好,根據客戶是重口味還是清淡,每一個imageLoader根據DisplayImageOptions的要求具體執行。

ImageLoaderConfiguration

在上面的示例程式碼中,我們使用ImageLoaderConfiguration的預設配置,下面給出ImageLoaderConfiguration比較詳盡的配置,從下面的配置中,可以看出ImageLoaderConfiguration的配置主要是全域性性的配置,主要有執行緒類、快取大小、磁碟大小、圖片下載與解析、日誌方面的配置。

複製程式碼
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
        .memoryCacheExtraOptions(480, 800) // default = device screen dimensions
        .diskCacheExtraOptions(480, 800, null)
        .taskExecutor(...)
        .taskExecutorForCachedImages(...)
        .threadPoolSize(3) // default
        .threadPriority(Thread.NORM_PRIORITY - 1) // default
        .tasksProcessingOrder(QueueProcessingType.FIFO) // default
        .denyCacheImageMultipleSizesInMemory()
        .memoryCache(new LruMemoryCache(2 * 1024 * 1024))
        .memoryCacheSize(2 * 1024 * 1024)
        .memoryCacheSizePercentage(13) // default
        .diskCache(new UnlimitedDiscCache(cacheDir)) // default
        .diskCacheSize(50 * 1024 * 1024)
        .diskCacheFileCount(100)
        .diskCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default
        .imageDownloader(new BaseImageDownloader(context)) // default
        .imageDecoder(new BaseImageDecoder()) // default
        .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default
        .writeDebugLogs()
        .build();
複製程式碼

ImageLoaderConfiguration的主要職責就是記錄相關的配置,它的內部其實就是一些欄位的集合(如下面的原始碼)。它有一個builder的內部類,這個類中的欄位跟ImageLoaderConfiguration中的欄位完全一致,它有一些預設值,通過修改builder可以配置ImageLoaderConfiguration。

複製程式碼
  1 /*******************************************************************************
  2  * Copyright 2011-2013 Sergey Tarasevich
  3  *
  4  * Licensed under the Apache License, Version 2.0 (the "License");
  5  * you may not use this file except in compliance with the License.
  6  * You may obtain a copy of the License at
  7  *
  8  * http://www.apache.org/licenses/LICENSE-2.0
  9  *
 10  * Unless required by applicable law or agreed to in writing, software
 11  * distributed under the License is distributed on an "AS IS" BASIS,
 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  * See the License for the specific language governing permissions and
 14  * limitations under the License.
 15  *******************************************************************************/
 16 package com.nostra13.universalimageloader.core;
 17 
 18 import android.content.Context;
 19 import android.content.res.Resources;
 20 import android.util.DisplayMetrics;
 21 import com.nostra13.universalimageloader.cache.disc.DiskCache;
 22 import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator;
 23 import com.nostra13.universalimageloader.cache.memory.MemoryCache;
 24 import com.nostra13.universalimageloader.cache.memory.impl.FuzzyKeyMemoryCache;
 25 import com.nostra13.universalimageloader.core.assist.FlushedInputStream;
 26 import com.nostra13.universalimageloader.core.assist.ImageSize;
 27 import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
 28 import com.nostra13.universalimageloader.core.decode.ImageDecoder;
 29 import com.nostra13.universalimageloader.core.download.ImageDownloader;
 30 import com.nostra13.universalimageloader.core.process.BitmapProcessor;
 31 import com.nostra13.universalimageloader.utils.L;
 32 import com.nostra13.universalimageloader.utils.MemoryCacheUtils;
 33 
 34 import java.io.IOException;
 35 import java.io.InputStream;
 36 import java.util.concurrent.Executor;
 37 
 38 /**
 39  * Presents configuration for {@link ImageLoader}
 40  *
 41  * @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
 42  * @see ImageLoader
 43  * @see MemoryCache
 44  * @see DiskCache
 45  * @see DisplayImageOptions
 46  * @see ImageDownloader
 47  * @see FileNameGenerator
 48  * @since 1.0.0
 49  */
 50 public final class ImageLoaderConfiguration {
 51 
 52     final Resources resources;
 53 
 54     final int maxImageWidthForMemoryCache;
 55     final int maxImageHeightForMemoryCache;
 56     final int maxImageWidthForDiskCache;
 57     final int maxImageHeightForDiskCache;
 58     final BitmapProcessor processorForDiskCache;
 59 
 60     final Executor taskExecutor;
 61     final Executor taskExecutorForCachedImages;
 62     final boolean customExecutor;
 63     final boolean customExecutorForCachedImages;
 64 
 65     final int threadPoolSize;
 66     final int threadPriority;
 67     final QueueProcessingType tasksProcessingType;
 68 
 69     final MemoryCache memoryCache;
 70     final DiskCache diskCache;
 71     final ImageDownloader downloader;
 72     final ImageDecoder decoder;
 73     final DisplayImageOptions defaultDisplayImageOptions;
 74 
 75     final ImageDownloader networkDeniedDownloader;
 76     final ImageDownloader slowNetworkDownloader;
 77 
 78     private ImageLoaderConfiguration(final Builder builder) {
 79         resources = builder.context.getResources();
 80         maxImageWidthForMemoryCache = builder.maxImageWidthForMemoryCache;
 81         maxImageHeightForMemoryCache = builder.maxImageHeightForMemoryCache;
 82         maxImageWidthForDiskCache = builder.maxImageWidthForDiskCache;
 83         maxImageHeightForDiskCache = builder.maxImageHeightForDiskCache;
 84         processorForDiskCache = builder.processorForDiskCache;
 85         taskExecutor = builder.taskExecutor;
 86         taskExecutorForCachedImages = builder.taskExecutorForCachedImages;
 87         threadPoolSize = builder.threadPoolSize;
 88         threadPriority = builder.threadPriority;
 89         tasksProcessingType = builder.tasksProcessingType;
 90         diskCache = builder.diskCache;
 91         memoryCache = builder.memoryCache;
 92         defaultDisplayImageOptions = builder.defaultDisplayImageOptions;
 93         downloader = builder.downloader;
 94         decoder = builder.decoder;
 95 
 96         customExecutor = builder.customExecutor;
 97         customExecutorForCachedImages = builder.customExecutorForCachedImages;
 98 
 99         networkDeniedDownloader = new NetworkDeniedImageDownloader(downloader);
100         slowNetworkDownloader = new SlowNetworkImageDownloader(downloader);
101 
102         L.writeDebugLogs(builder.writeLogs);
103     }
104 
105     /**
106      * Creates default configuration for {@link ImageLoader} <br />
107      * <b>Default values:</b>
108      * <ul>
109      * <li>maxImageWidthForMemoryCache = device's screen width</li>
110      * <li>maxImageHeightForMemoryCache = device's screen height</li>
111      * <li>maxImageWidthForDikcCache = unlimited</li>
112      * <li>maxImageHeightForDiskCache = unlimited</li>
113      * <li>threadPoolSize = {@link Builder#DEFAULT_THREAD_POOL_SIZE this}</li>
114      * <li>threadPriority = {@link Builder#DEFAULT_THREAD_PRIORITY this}</li>
115      * <li>allow to cache different sizes of image in memory</li>
116      * <li>memoryCache = {@link DefaultConfigurationFactory#createMemoryCache(int)}</li>
117      * <li>diskCache = {@link com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache}</li>
118      * <li>imageDownloader = {@link DefaultConfigurationFactory#createImageDownloader(Context)}</li>
119      * <li>imageDecoder = {@link DefaultConfigurationFactory#createImageDecoder(boolean)}</li>
120      * <li>diskCacheFileNameGenerator = {@link DefaultConfigurationFactory#createFileNameGenerator()}</li>
121      * <li>defaultDisplayImageOptions = {@link DisplayImageOptions#createSimple() Simple options}</li>
122      * <li>tasksProcessingOrder = {@link QueueProcessingType#FIFO}<