史上最全Universal-Image-Loader原始碼解析————核心程式碼篇
阿新 • • 發佈:2019-01-04
背景
接著上一篇的內容,我們接著看ImageLoader的核心程式碼篇,上一篇主要是看ImageLoader的記憶體優化,主要包括磁碟快取和記憶體快取,還有就是記憶體的快取策略,這一篇,我們重點來看一下ImageLoader是如何使用這些記憶體和進行圖片的展示和圖片處理和下載的。
一、code組織框架
首先我們先看code包下面的組織框架,然後我們再每個類去分析,最後我們全部串起來學習。核心程式碼篇和上一篇快取篇不一樣,核心程式碼量較多,但是我們部落格篇幅有限,我們只能按重要程度,將大部分進行講解,不多說先上截圖。
二 、詳細程式碼及類講解
(1)ImageLoader
這個類可能是開發者最先接觸或者說印象最深刻的類了,我們來看一下我們是怎麼接觸它的,我們來看一下它的最簡單使用和原始碼的實現。
//建立預設的ImageLoader配置引數
ImageLoaderConfiguration configuration = ImageLoaderConfiguration
.createDefault(this);
ImageLoader.getInstance().init(configuration);
ImageLoader.getInstance().displayImage (imageUrl, mImageView, options);
/**
* ImageLoader是核心主類之一
*/
public class ImageLoader {
public static final String TAG = ImageLoader.class.getSimpleName();
static final String LOG_INIT_CONFIG = "Initialize ImageLoader with configuration";
static final String LOG_DESTROY = "Destroy ImageLoader" ;
static final String LOG_LOAD_IMAGE_FROM_MEMORY_CACHE = "Load image from memory cache [%s]";
private static final String WARNING_RE_INIT_CONFIG = "Try to initialize ImageLoader which had already been initialized before. " + "To re-init ImageLoader with new configuration call ImageLoader.destroy() at first.";
private static final String ERROR_WRONG_ARGUMENTS = "Wrong arguments were passed to displayImage() method (ImageView reference must not be null)";
private static final String ERROR_NOT_INIT = "ImageLoader must be init with configuration before using";
private static final String ERROR_INIT_CONFIG_WITH_NULL = "ImageLoader configuration can not be initialized with null";
private ImageLoaderConfiguration configuration;//引數
private ImageLoaderEngine engine;//核心
//預設是使用簡單的監聽器
private ImageLoadingListener defaultListener = new SimpleImageLoadingListener();
private volatile static ImageLoader instance;
/**
* 先來個單例模式
*/
public static ImageLoader getInstance() {
if (instance == null) {
synchronized (ImageLoader.class) {
if (instance == null) {
instance = new ImageLoader();
}
}
}
return instance;
}
protected ImageLoader() {
}
/**
* 使用者先配置引數然後初始化進來
*/
public synchronized void init(ImageLoaderConfiguration configuration) {
if (configuration == null) {
throw new IllegalArgumentException(ERROR_INIT_CONFIG_WITH_NULL);
}
if (this.configuration == null) {
engine = new ImageLoaderEngine(configuration);
this.configuration = configuration;
} else {
}
}
/**
* 判斷是否被初始化
*/
public boolean isInited() {
return configuration != null;
}
/**
* 多級呼叫 將imageview轉化為imageAware
*/
public void displayImage(String uri, ImageAware imageAware) {
displayImage(uri, imageAware, null, null, null);
}
/**
* 多級呼叫加監聽
*/
public void displayImage(String uri, ImageAware imageAware, ImageLoadingListener listener) {
displayImage(uri, imageAware, null, listener, null);
}
/**
* 呼叫加展示引數
*/
public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options) {
displayImage(uri, imageAware, options, null, null);
}
/**
* 進行多級呼叫 兩者都有
*/
public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options,
ImageLoadingListener listener) {
displayImage(uri, imageAware, options, listener, null);
}
/**
* 這個引數有加了引數和監聽器和進度條監聽器
*/
public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options,
ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {
displayImage(uri, imageAware, options, null, listener, progressListener);
}
/**
* 所有方法最終走到這裡
*/
public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options,
ImageSize targetSize, ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {
checkConfiguration();//檢查 是否有配置檔案
if (imageAware == null) {//都是判斷了
throw new IllegalArgumentException(ERROR_WRONG_ARGUMENTS);
}
if (listener == null) {
listener = defaultListener;
}
if (options == null) {
options = configuration.defaultDisplayImageOptions;
}
if (TextUtils.isEmpty(uri)) {//第一行 判斷uri是否是空 如果是空 直接取消engine中的任務
engine.cancelDisplayTaskFor(imageAware);
listener.onLoadingStarted(uri, imageAware.getWrappedView());//然後呼叫listener的start
if (options.shouldShowImageForEmptyUri()) {//由於 uri為空 如果設定了需要設定空的影象那麼直接設定 影象是 空的時候需要設定的影象即可 如果沒設定,直接不顯示就好
imageAware.setImageDrawable(options.getImageForEmptyUri(configuration.resources));
} else {
imageAware.setImageDrawable(null);
}//之後呼叫 complete 回撥 返回 這是uri為空的情況 不需要做太多操作 也不需要快取
listener.onLoadingComplete(uri, imageAware.getWrappedView(), null);
return;
}
if (targetSize == null) {//像的大小 設定是空 那麼根據控制元件設定的大小 設定 要展示圖片的大小
targetSize = ImageSizeUtils.defineTargetSizeForView(imageAware, configuration.getMaxImageSize());
}
//之後 根據 uri和目標的大小 生成一個key 並把 這個任務放入 engine 的集合中
// 回撥 started方法
String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize);
engine.prepareDisplayTaskFor(imageAware, memoryCacheKey);
listener.onLoadingStarted(uri, imageAware.getWrappedView());
// 從記憶體快取中根據key取bitmap
Bitmap bmp = configuration.memoryCache.get(memoryCacheKey);
//如果存在 並且沒被回收
if (bmp != null && !bmp.isRecycled()) {
//如果設定了 postProcess 執行 預設沒設定 設定這個可以提前對圖片進行某些處理
if (options.shouldPostProcess()) {
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()) {
displayTask.run();
} else {
engine.submit(displayTask);
}
} else {
//不需要 在展示圖片之前處理圖片時,那麼就直接使用 displaywe 對 圖片進行 展示 並回調complete函式
options.getDisplayer().display(bmp, imageAware, LoadedFrom.MEMORY_CACHE);
listener.onLoadingComplete(uri, imageAware.getWrappedView(), bmp);
}
} else {//如果不存在記憶體快取中 或者已經被回收了
if (options.shouldShowImageOnLoading()) {//如果載入時需要顯示圖片 那麼設定 否則 不設定圖片
imageAware.setImageDrawable(options.getImageOnLoading(configuration.resources));
} else if (options.isResetViewBeforeLoading()) {
imageAware.setImageDrawable(null);
}
//然後 設定正在載入時的資訊 ImageLoadingInfo 和 任務LoadAndDisplayImageTask
ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey,
options, listener, progressListener, engine.getLockForUri(uri));
LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(engine, imageLoadingInfo,
defineHandler(options));
if (options.isSyncLoading()) {//根據是否同步 執行任務
displayTask.run();
} else {
engine.submit(displayTask);
}
}
}
/**
* 使用者直接在外面呼叫的,裡面將他轉成了ImageViewAware
*/
public void displayImage(String uri, ImageView imageView) {
displayImage(uri, new ImageViewAware(imageView), null, null, null);
}
/**
* 展示圖片新增圖片大小
*/
public void displayImage(String uri, ImageView imageView, ImageSize targetImageSize) {
displayImage(uri, new ImageViewAware(imageView), null, targetImageSize, null, null);
}
/**
* 展示圖片加引數
*/
public void displayImage(String uri, ImageView imageView, DisplayImageOptions options) {
displayImage(uri, new ImageViewAware(imageView), options, null, null);
}
/**
* 圖片加監聽
*/
public void displayImage(String uri, ImageView imageView, ImageLoadingListener listener) {
displayImage(uri, new ImageViewAware(imageView), null, listener, null);
}
public void displayImage(String uri, ImageView imageView, DisplayImageOptions options,
ImageLoadingListener listener) {
displayImage(uri, imageView, options, listener, null);
}
/**
* 展示圖片加監聽加進度條
*/
public void displayImage(String uri, ImageView imageView, DisplayImageOptions options,
ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {
displayImage(uri, new ImageViewAware(imageView), options, listener, progressListener);
}
/**
* 展示圖片加監聽
*/
public void loadImage(String uri, ImageLoadingListener listener) {
loadImage(uri, null, null, listener, null);
}
/**
* 展示圖片加記憶體限制加監聽
*/
public void loadImage(String uri, ImageSize targetImageSize, ImageLoadingListener listener) {
loadImage(uri, targetImageSize, null, listener, null);
}
/**
*/
public void loadImage(String uri, DisplayImageOptions options, ImageLoadingListener listener) {
loadImage(uri, null, options, listener, null);
}
/**
* 展示圖片加目標大小
*/
public void loadImage(String uri, ImageSize targetImageSize, DisplayImageOptions options,
ImageLoadingListener listener) {
loadImage(uri, targetImageSize, options, listener, null);
}
/**
* 展示圖片 所有引數都加
*/
public void loadImage(String uri, ImageSize targetImageSize, DisplayImageOptions options,
ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {
checkConfiguration();
if (targetImageSize == null) {
targetImageSize = configuration.getMaxImageSize();
}
if (options == null) {
options = configuration.defaultDisplayImageOptions;
}
NonViewAware imageAware = new NonViewAware(uri, targetImageSize, ViewScaleType.CROP);
displayImage(uri, imageAware, options, listener, progressListener);
}
/**
* 載入圖片 非同步的
*/
public Bitmap loadImageSync(String uri) {
return loadImageSync(uri, null, null);
}
/**
* 載入圖片非同步加引數
*/
public Bitmap loadImageSync(String uri, DisplayImageOptions options) {
return loadImageSync(uri, null, options);
}
/**
* 載入圖片限制圖片大小
*/
public Bitmap loadImageSync(String uri, ImageSize targetImageSize) {
return loadImageSync(uri, targetImageSize, null);
}
/**
* 載入圖片非同步
*/
public Bitmap loadImageSync(String uri, ImageSize targetImageSize, DisplayImageOptions options) {
if (options == null) {
options = configuration.defaultDisplayImageOptions;
}
options = new DisplayImageOptions.Builder().cloneFrom(options).syncLoading(true).build();
SyncImageLoadingListener listener = new SyncImageLoadingListener();
loadImage(uri, targetImageSize, options, listener);
return listener.getLoadedBitmap();
}
/**
* Checks if ImageLoader's configuration was initialized
* 檢查配置
*/
private void checkConfiguration() {
if (configuration == null) {
throw new IllegalStateException(ERROR_NOT_INIT);
}
}
/**
* 設定監聽器.
*/
public void setDefaultLoadingListener(ImageLoadingListener listener) {
defaultListener = listener == null ? new SimpleImageLoadingListener() : listener;
}
/**
* Returns memory cache
* 返回記憶體策略
*
* @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before
*/
public MemoryCache getMemoryCache() {
checkConfiguration();
return configuration.memoryCache;
}
/**
* Clears memory cache
*
* @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before
*/
public void clearMemoryCache() {
checkConfiguration();
configuration.memoryCache.clear();
}
/**
* Returns disk cache
* 返回磁碟快取
*
* @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before
* @deprecated Use {@link #getDiskCache()} instead
*/
@Deprecated
public DiskCache getDiscCache() {
return getDiskCache();
}
/**
* Returns disk cache
*
* @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before
*/
public DiskCache getDiskCache() {
checkConfiguration();
return configuration.diskCache;
}
/**
* Clears disk cache.
*/
@Deprecated
public void clearDiscCache() {
clearDiskCache();
}
/**
* Clears disk cache.
*/
public void clearDiskCache() {
checkConfiguration();
configuration.diskCache.clear();
}
/**
* Returns URI of image which is loading at this moment into passed
*/
public String getLoadingUriForView(ImageAware imageAware) {
return engine.getLoadingUriForView(imageAware);
}
/**
* Returns URI of image which is loading at this moment into passed
*/
public String getLoadingUriForView(ImageView imageView) {
return engine.getLoadingUriForView(new ImageViewAware(imageView));
}
/**
* Cancel the task of loading and displaying image for passed
* which display task will be cancelled
*/
public void cancelDisplayTask(ImageAware imageAware) {
engine.cancelDisplayTaskFor(imageAware);
}
/**
*/
public void cancelDisplayTask(ImageView imageView) {
engine.cancelDisplayTaskFor(new ImageViewAware(imageView));
}
/**
* 拒絕網路下載
*/
public void denyNetworkDownloads(boolean denyNetworkDownloads) {
engine.denyNetworkDownloads(denyNetworkDownloads);
}
/**
* 處理網路慢
* - otherwise.
*/
public void handleSlowNetwork(boolean handleSlowNetwork) {
engine.handleSlowNetwork(handleSlowNetwork);
}
/**
*/
public void pause() {
engine.pause();
}
/**
*
*/
public void resume() {
engine.resume();
}
/**
*/
public void stop() {
engine.stop();
}
/**
* 銷燬
*/
public void destroy() {
stop();
configuration.diskCache.close();
engine = null;
configuration = null;
}
private static Handler defineHandler(DisplayImageOptions options) {
Handler handler = options.getHandler();
if (options.isSyncLoading()) {
handler = null;
} else if (handler == null && Looper.myLooper() == Looper.getMainLooper()) {
handler = new Handler();
}
return handler;
}
/**
* Listener which is designed for synchronous image loading.
*/
private static class SyncImageLoadingListener extends SimpleImageLoadingListener {
private Bitmap loadedImage;
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
this.loadedImage = loadedImage;
}
public Bitmap getLoadedBitmap() {
return loadedImage;
}
}
}
(2)DefaultConfigurationFactory
這個類是一個使用工廠模式方法提供一個隊imageloader的引數配置,通過這個類,可以建立一系列的配置引數,通過程式碼我們可以清楚的看到,它預設使用hashcode的磁碟命名,如果磁碟沒有傳大小,那麼就會使用無限的磁碟快取策略,如果有傳大小的話,那麼就使用最近最少使用的磁碟快取策略,記憶體快取的話,如果有傳大小,那麼使用這個傳的大小,如果沒有穿引數的話,那麼就使用app最大的八分之一,使用最近最少快取策略,還有就是建立一些圖片展示器之類的。
/**
* Factory for providing of default options for {@linkplain ImageLoaderConfiguration configuration}
*一個工廠提供預設的操作對imageloader的引數
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
* @since 1.5.6
*/
public class DefaultConfigurationFactory {
/** 建立一個預設的執行器 */
public static Executor createExecutor(int threadPoolSize, int threadPriority,
QueueProcessingType tasksProcessingType) {
boolean lifo = tasksProcessingType == QueueProcessingType.LIFO;
BlockingQueue<Runnable> taskQueue =
lifo ? new LIFOLinkedBlockingDeque<Runnable>() : new LinkedBlockingQueue<Runnable>();
return new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0L, TimeUnit.MILLISECONDS, taskQueue,
createThreadFactory(threadPriority, "uil-pool-"));
}
/** /預設的任務分發Executor */
public static Executor createTaskDistributor() {
return Executors.newCachedThreadPool(createThreadFactory(Thread.NORM_PRIORITY, "uil-pool-d-"));
}
/**預設的磁碟快取檔名的生成策略 */
public static FileNameGenerator createFileNameGenerator() {
return new HashCodeFileNameGenerator();
}
/**
* 預設的硬體快取配置 如果值為0的話就用無限的磁碟快取 如果大於0就用最近最少使用快取
*/
public static DiskCache createDiskCache(Context context, FileNameGenerator diskCacheFileNameGenerator,
long diskCacheSize, int diskCacheFileCount) {
File reserveCacheDir = createReserveDiskCacheDir(context);
if (diskCacheSize > 0 || diskCacheFileCount > 0) {
File individualCacheDir = StorageUtils.getIndividualCacheDirectory(context);
try {
return new LruDiskCache(individualCacheDir, reserveCacheDir, diskCacheFileNameGenerator, diskCacheSize,
diskCacheFileCount);
} catch (IOException e) {
L.e(e);
// continue and create unlimited cache
}
}
File cacheDir = StorageUtils.getCacheDirectory(context);
return new UnlimitedDiskCache(cacheDir, reserveCacheDir, diskCacheFileNameGenerator);
}
/** Creates reserve disk cache folder which will be used if primary disk cache folder becomes unavailable */
private static File createReserveDiskCacheDir(Context context) {//預設的備用硬體快取目錄
File cacheDir = StorageUtils.getCacheDirectory(context, false);
File individualDir = new File(cacheDir, "uil-images");
if (individualDir.exists() || individualDir.mkdir()) {
cacheDir = individualDir;
}
return cacheDir;
}
/**
* Creates default implementation of {@link MemoryCache} - {@link LruMemoryCache}<br />
* Default cache size = 1/8 of available app memory.
*
* 配置 如果傳入的預設大小為0 那麼就拿到App最大記憶體的八分之一
* 如果不為0 那麼就用傳入的大小來作為最近最少使用演算法的記憶體
*/
public static MemoryCache createMemoryCache(Context context, int memoryCacheSize) {
if (memoryCacheSize == 0) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
int memoryClass = am.getMemoryClass();
if (hasHoneycomb() && isLargeHeap(context)) {
memoryClass = getLargeMemoryClass(am);
}
memoryCacheSize = 1024 * 1024 * memoryClass / 8;
}
return new LruMemoryCache(memoryCacheSize);
}
private static boolean hasHoneycomb() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private static boolean isLargeHeap(Context context) {
return (context.getApplicationInfo().flags & ApplicationInfo.FLAG_LARGE_HEAP) != 0;
}
//
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private static int getLargeMemoryClass(ActivityManager am) {
return am.getLargeMemoryClass();
}
//建立一個圖片下載器
/** Creates default implementation of {@link ImageDownloader} - {@link BaseImageDownloader} */
public static ImageDownloader createImageDownloader(Context context) {
return new BaseImageDownloader(context);
}
//建立一個圖片修改器
/** Creates default implementation of {@link ImageDecoder} - {@link BaseImageDecoder} */
public static ImageDecoder createImageDecoder(boolean loggingEnabled) {
return new BaseImageDecoder(loggingEnabled);
}
//預設的BitmapDisplayer
/** Creates default implementation of {@link BitmapDisplayer} - {@link SimpleBitmapDisplayer} */
public static BitmapDisplayer createBitmapDisplayer() {
return new SimpleBitmapDisplayer();
}
//預設的TreadFactory
/** Creates default implementation of {@linkplain ThreadFactory thread factory} for task executor */
private static ThreadFactory createThreadFactory(int threadPriority, String threadNamePrefix) {
return new DefaultThreadFactory(threadPriority, threadNamePrefix);
}
private static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
private final int threadPriority;
DefaultThreadFactory(int threadPriority, String threadNamePrefix) {
this.threadPriority = threadPriority;
group = Thread.currentThread().getThreadGroup();
namePrefix = threadNamePrefix + poolNumber.getAndIncrement() + "-thread-";
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
if (t.isDaemon()) t.setDaemon(false);
t.setPriority(threadPriority);
return t;
}
}
}
(3)DisplayBitmapTask
一個顯示圖片任務的類,開了一個子執行緒實現Runnable介面,主要是run的一個判斷,註解才是重點
/**
*顯示圖片任務的一個類
*/
final class DisplayBitmapTask implements Runnable {
private static final String LOG_DISPLAY_IMAGE_IN_IMAGEAWARE = "Display image in ImageAware (loaded from %1$s) [%2$s]";
private static final String LOG_TASK_CANCELLED_IMAGEAWARE_REUSED = "ImageAware is reused for another image. Task is cancelled. [%s]";
private static final String LOG_TASK_CANCELLED_IMAGEAWARE_COLLECTED = "ImageAware was collected by GC. Task is cancelled. [%s]";
private final Bitmap bitmap;
private final String imageUri;//
private final ImageAware imageAware;//
private final String memoryCacheKey;
private final BitmapDisplayer displayer;
private final ImageLoadingListener listener;
private final ImageLoaderEngine engine;
private final LoadedFrom loadedFrom;
//初始化
public DisplayBitmapTask(Bitmap bitmap, ImageLoadingInfo imageLoadingInfo, ImageLoaderEngine engine,
LoadedFrom loadedFrom) {
this.bitmap = bitmap;
imageUri = imageLoadingInfo.uri;
imageAware = imageLoadingInfo.imageAware;
memoryCacheKey = imageLoadingInfo.memoryCacheKey;
displayer = imageLoadingInfo.options.getDisplayer();
listener = imageLoadingInfo.listener;
this.engine = engine;
this.loadedFrom = loadedFrom;
}
@Override
public void run() {
if (imageAware.isCollected()) {//判斷圖片View是否已經被回收了,如果已經被回收,則取消任務
L.d(LOG_TASK_CANCELLED_IMAGEAWARE_COLLECTED, memoryCacheKey);
listener.onLoadingCancelled(imageUri, imageAware.getWrappedView());
} else if (isViewWasReused()) {//圖片View是否又用來展示其他圖片了,如果是的話,則取消任務
L.d(LOG_TASK_CANCELLED_IMAGEAWARE_REUSED, memoryCacheKey);
listener.onLoadingCancelled(imageUri, imageAware.getWrappedView());
} else {//展示圖片 完成介面回撥
L.d(LOG_DISPLAY_IMAGE_IN_IMAGEAWARE, loadedFrom, memoryCacheKey);
displayer.display(bitmap, imageAware, loadedFrom);
engine.cancelDisplayTaskFor(imageAware);
listener.onLoadingComplete(imageUri, imageAware.getWrappedView(), bitmap);
}
}
/** 檢查imageview是否有效 */
private boolean isViewWasReused() {
String currentCacheKey = engine.getLoadingUriForView(imageAware);
return !memoryCacheKey.equals(currentCacheKey);
}
}
(4)DisplayImageOptions
展示圖片的一個引數操作,展示的時候傳入引數,展示的圖片會根據傳入的引數進行展示。
/**
* 展示圖片的一個引數操作
*/
public final class DisplayImageOptions {
private final int imageResOnLoading;
private final int imageResForEmptyUri;
private final int imageResOnFail;
private final Drawable imageOnLoading;
private final Drawable imageForEmptyUri;
private final Drawable imageOnFail;
private final boolean resetViewBeforeLoading;
private final boolean cacheInMemory;
private final boolean cacheOnDisk;
private final ImageScaleType imageScaleType;
private final Options decodingOptions;
private final int delayBeforeLoading;
private final boolean considerExifParams;
private final Object extraForDownloader;
private final BitmapProcessor preProcessor;
private final BitmapProcessor postProcessor;
private final BitmapDisplayer displayer;
private final Handler handler;
private final boolean isSyncLoading;
private DisplayImageOptions(Builder builder) {
imageResOnLoading = builder.imageResOnLoading;
imageResForEmptyUri = builder.imageResForEmptyUri;
imageResOnFail = builder.imageResOnFail;
imageOnLoading = builder.imageOnLoading;
imageForEmptyUri = builder.imageForEmptyUri;
imageOnFail = builder.imageOnFail;
resetViewBeforeLoading = builder.resetViewBeforeLoading;
cacheInMemory = builder.cacheInMemory;
cacheOnDisk = builder.cacheOnDisk;
imageScaleType = builder.imageScaleType;
decodingOptions = builder.decodingOptions;
delayBeforeLoading = builder.delayBeforeLoading;
considerExifParams = builder.considerExifParams;
extraForDownloader = builder.extraForDownloader;
preProcessor = builder.preProcessor;
postProcessor = builder.postProcessor;
displayer = builder.displayer;
handler = builder.handler;
isSyncLoading = builder.isSyncLoading;
}
//判斷是否在下載的時候需要顯示圖片
public boolean shouldShowImageOnLoading() {
return imageOnLoading != null || imageResOnLoading != 0;
}
//空uri的時候是否需要顯示圖片
public boolean shouldShowImageForEmptyUri() {
return imageForEmptyUri != null || imageResForEmptyUri != 0;
}
//是否需要顯示圖片在下載失敗的時候
public boolean shouldShowImageOnFail() {
return imageOnFail != null || imageResOnFail != 0;
}
//是否應該提前處理圖片
public boolean shouldPreProcess() {
return preProcessor != null;
}
//是否後面需要處理圖片
public boolean shouldPostProcess() {
return postProcessor != null;
}
//是否延遲載入圖片
public boolean shouldDelayBeforeLoading() {
return delayBeforeLoading > 0;
}
//拿到圖片
public Drawable getImageOnLoading(Resources res) {
return imageResOnLoading != 0 ? res.getDrawable(imageResOnLoading) : imageOnLoading;
}
//拿到圖片
public Drawable getImageForEmptyUri(Resources res) {
return imageResForEmptyUri != 0 ? res.getDrawable(imageResForEmptyUri) : imageForEmptyUri;
}
//拿到圖片
public Drawable getImageOnFail(Resources res) {
return imageResOnFail != 0 ? res.getDrawable(imageResOnFail) : imageOnFail;
}
//是否重置view
public boolean isResetViewBeforeLoading() {
return resetViewBeforeLoading;
}
//要不要存到記憶體中
public boolean isCacheInMemory() {
return cacheInMemory;
}
//要不要存到磁碟中
public boolean isCacheOnDisk() {
return cacheOnDisk;
}
//縮放型別
public ImageScaleType getImageScaleType() {
return imageScaleType;
}
//操作型別
public Options getDecodingOptions() {
return decodingOptions;
}
//延遲載入
public int getDelayBeforeLoading() {
return delayBeforeLoading;
}
public boolean isConsiderExifParams() {
return considerExifParams;
}
//拿到額外新增引數
public Object getExtraForDownloader() {
return extraForDownloader;
}
//拿到提前處理
public BitmapProcessor getPreProcessor() {
return preProcessor;
}
//拿到處理後
public BitmapProcessor getPostProcessor() {
return postProcessor;
}
//拿到展示器
public BitmapDisplayer getDisplayer() {
return displayer;
}
public Handler getHandler() {
return handler;
}
boolean isSyncLoading() {
return isSyncLoading;
}
/**
* Builder for {@link DisplayImageOptions}
*/
public static class Builder {
private int imageResOnLoading = 0; //在圖片下載期間顯示的圖片
private int imageResForEmptyUri = 0;//設定圖片Uri為空或是錯誤的時候顯示的圖片
private int imageResOnFail = 0; //設定圖片載入/解碼過程中錯誤時候顯示的圖片
private Drawable imageOnLoading = null;//在圖片下載期間顯示的圖片
private Drawable imageForEmptyUri = null;//設定圖片Uri為空或是錯誤的時候顯示的圖片
private Drawable imageOnFail = null;//設定圖片載入/解碼過程中錯誤時候顯示的圖片
private boolean resetViewBeforeLoading = false; //設定圖片在下載前是否重置,復位
private boolean cacheInMemory = false;//設定下載的圖片是否快取在記憶體中
private boolean cacheOnDisk = false; //設定下載的圖片是否快取在SD卡中
private ImageScaleType imageScaleType = ImageScaleType.IN_SAMPLE_POWER_OF_2;
private Options decodingOptions = new Options(); //設定圖片的解碼型別 //設定圖片的解碼配置
private int delayBeforeLoading = 0;//設定圖片下載前的延遲
private boolean considerExifParams = false;//設定圖片以如何的編碼方式顯示
private Object extraForDownloader = null;//設定額外的內容給ImageDownloade
private BitmapProcessor preProcessor = null;//設定圖片加入快取前,對bitmap進行設定
private BitmapProcessor postProcessor = null; //設定顯示前的圖片,顯示後這個圖片一直保留在快取中
private BitmapDisplayer displayer = DefaultConfigurationFactory.createBitmapDisplayer();
private Handler handler = null;
private boolean isSyncLoading = false;
/**
* 設定引數欄位參考上面註釋
*/
@Deprecated
public Builder showStubImage(int imageRes) {
imageResOnLoading = imageRes;
return this;
}
/**
* 設定引數欄位參考上面註釋
*/
public Builder showImageOnLoading(int imageRes) {
imageResOnLoading = imageRes;
return this;
}
/**
* 設定引數欄位參考上面註釋
*/
public Builder showImageOnLoading(Drawable drawable) {
imageOnLoading = drawable;
return this;
}
/**
* 設定引數欄位參考上面註釋
*/