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 = newImageLoaderConfiguration.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 voidonCreate(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}<