Image-Loader是一個(gè)很不錯(cuò)的圖片加載框架,只需要簡單的配置就能完成緩存,圖片下載,顯示圖片這些工作,Image-Loader的GitHub地址 https://github.com/nostra13/Android-Universal-Image-Loader ,各位可以去這里看到Image-Loader的源碼,至于有什么寫的不好的地方,還望見諒。
首先看一下Image-Loader的代碼結(jié)構(gòu)

cache里是緩存相關(guān)的類,core里是Image-Loader的核心功能類,utils里是一些常用的工具類。
Image-Loader的用法相信各位都比較清楚:如下:
<code>ImageLoader imageLoader = ImageLoader.getInstance(); //獲取實(shí)例
imageLoader.init(ImageLoaderConfiguration); //初始化ImageLoader
imageLoader.displayImage(imageUri, imageView); //顯示圖片
imageLoader.loadImage(imageUri, new SimpleImageLoadingListener() {
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
// Do whatever you want with Bitmap
}
});
Bitmap bmp = imageLoader.loadImageSync(imageUri); //異步獲取Bitmap
</code>
用法特別簡單,也非常實(shí)用,下面我們來一點(diǎn)一點(diǎn)分析一下,Image-Loader的原理。
當(dāng)然在這兒必須先把這張圖拋出來:

這張圖相信大家都能看得懂,大概意思是需要加載圖片的時(shí)候,先看Bitmap是否在內(nèi)存中,如果在內(nèi)存中就直接用PostprocessBitmap 、 DisplayBitmap去顯示圖片。如果內(nèi)存中沒有,就去看Disk 中有沒有,如果Disk中有就把它拿出來放到內(nèi)存中去,然后顯示圖片。如果DIsk中也沒有就去下載這個(gè)圖片然后再把它緩存到Disk中、內(nèi)存中、顯示圖片。
這是Image-Loader加載圖片的流程,大概的工作原理,具體是怎么實(shí)現(xiàn)的呢,下面我們來一點(diǎn)點(diǎn)分析哈
首先打開Imageloader這個(gè)類

可以看到有一個(gè)ImageLoaderConfiguration,一個(gè)ImageLoaderEngine,一個(gè)ImageLoadingListener。這 三個(gè)東西到底是干嘛的呢?
ImageloaderConfighration是用來配置Imageloader的各個(gè)屬性的,ImageloaderConfguration采用了Builder構(gòu)建方法來配置ImageloaderConfiguration的各個(gè)參數(shù)看下面這張圖:

在這個(gè)里面有一個(gè)defaultDisplayImageOptions方法,這個(gè)方法用來設(shè)置顯示圖片的一些操作,比如圖片的壓縮方式。
這個(gè)是Imagloader的總體設(shè)計(jì)圖,最頂層的是Imagloader,Imageloader實(shí)現(xiàn)了兩個(gè)最常用的方法displayImage、loadImage。這兩個(gè)方法里又需要ImagloaderEngine來實(shí)現(xiàn)相關(guān)Task的分發(fā)處理,然后去顯示圖片。

其實(shí)ImageLoader所有的東西都在這個(gè)流程圖中,這個(gè)流程圖詳細(xì)解釋了顯示圖片ImageLoader所做的操作。對著代碼研讀完這個(gè)圖片你就清楚整個(gè)Imagelaoder的原理了貼上代碼:
<code>
if (TextUtils.isEmpty(uri)) { //uri 為空的時(shí)候
engine.cancelDisplayTaskFor(imageAware); //ImageloaderEngine 取消顯示圖片
listener.onLoadingStarted(uri, imageAware.getWrappedView()); //去加載默認(rèn)圖片
if (options.shouldShowImageForEmptyUri()) { //如果option中設(shè)置了空圖片就顯示空圖片
imageAware.setImageDrawable(options.getImageForEmptyUri(configuration.resources));
} else {
imageAware.setImageDrawable(null); //否則就不顯示
}
listener.onLoadingComplete(uri, imageAware.getWrappedView(), null); //顯示完成!
return;
}
if (targetSize == null) { //如果不要求圖片大小的話 就顯示所獲得的圖片的最大值
targetSize = ImageSizeUtils.defineTargetSizeForView(imageAware, configuration.getMaxImageSize());
}
String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize); //從內(nèi)存中取出緩存中的圖片
engine.prepareDisplayTaskFor(imageAware, memoryCacheKey); //開始準(zhǔn)備顯示圖片
listener.onLoadingStarted(uri, imageAware.getWrappedView()); //顯示加載中的圖片
Bitmap bmp = configuration.memoryCache.get(memoryCacheKey); //去出緩存中的Bitmap
if (bmp != null && !bmp.isRecycled()) { //如果圖片在緩存中,并且bitmap沒有被回收
L.d(LOG_LOAD_IMAGE_FROM_MEMORY_CACHE, memoryCacheKey); //打印出這個(gè)圖片的memoryCacheKey
if (options.shouldPostProcess()) { //如果說在DisplayImageOptions設(shè)置了postProcess就是是否重新處理bitmap 就開始重新處理并且顯示
ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey,
options, listener, progressListener, engine.getLockForUri(uri));
ProcessAndDisplayImageTask displayTask = new ProcessAndDisplayImageTask(engine, bmp, imageLoadingInfo,
defineHandler(options));
if (options.isSyncLoading()) { //如果是異步顯示 就直接run
displayTask.run();
} else { //否則提交到線程池中
engine.submit(displayTask);
}
} else { //否則就開始直接顯示顯示
options.getDisplayer().display(bmp, imageAware, LoadedFrom.MEMORY_CACHE);
listener.onLoadingComplete(uri, imageAware.getWrappedView(), bmp); //監(jiān)聽接口的回調(diào)
}
} else { //如果說緩存中拿不到這個(gè)圖片,就開始重新下載
if (options.shouldShowImageOnLoading()) { //是否顯示加載中的圖片
imageAware.setImageDrawable(options.getImageOnLoading(configuration.resources));
} else if (options.isResetViewBeforeLoading()) {
imageAware.setImageDrawable(null);
}
ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey,
options, listener, progressListener, engine.getLockForUri(uri));
LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(engine, imageLoadingInfo,
defineHandler(options)); //下載并且顯示這個(gè)圖片,這里面包含了下載圖片,緩存圖片處理bitmap等等操作 具體的可以去看這個(gè)LoadAndDisplyImageTask這個(gè)runnable里怎么寫的,也許下文中會(huì)解釋一下這個(gè)過程
if (options.isSyncLoading()) {
displayTask.run();
} else {
engine.submit(displayTask);
}
}
</code>
display-image-flow-chart.png
