智能手机的普遍使用,使人们不再满足于文字以及少量图标显示。考虑到之前手机内存的限制与app安装包的体量大小,选择使用加载网络图片到app是一个很好的选择,但是大量的加载图片又会引发其他问题,比如:让用户产生过多流量费用、图片加载速度的提升等,这就要求对图片进行缓存;内存溢出(Out Of Memery,简称OOM),这就要求对加载的图片进行处理。有好多第三方开源框架做的比较成熟,比如ImageLoader、Picasso、Fresco、Glide等,道长今天说说ImageLoader。
支持下载进度监听
可以在View滚动中暂停图片加载
通过 PauseOnScrollListener 接口可以在 View 滚动中暂停图片加载。
默认实现多种内存缓存算法
ImageLoader 默认实现了较多缓存算法,如 Size 最大先删除、使用最少先删除、最近最少使用、先进先删除、时间最长先删除等。
支持本地缓存文件名规则定义
private static void initImageLoader(Context context) {
File cacheDir = StorageUtils.getOwnCacheDirectory(context,
"yushan/iamgeloader");
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
.cacheInMemory(true).cacheOnDisc(true)
.bitmapConfig(Config.RGB_565)// 设置图片解码类型
.imageScaleType(ImageScaleType.IN_SAMPLE_INT)
.considerExifParams(false)// 不考虑iamge的翻转
.build();
// 基本配置
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
context)
.denyCacheImageMultipleSizesInMemory() // 一个URL只缓存一张图片
.discCacheFileNameGenerator(new Md5FileNameGenerator())// 文件名MD5加密
.defaultDisplayImageOptions(defaultOptions)
.discCache(new UnlimitedDiscCache(cacheDir)) // 自定义缓存路径
.discCacheSize(50 * 1024 * 1024) // 磁盘缓存大小
.discCacheFileCount(100) // 缓存100图片
.memoryCache(new WeakMemoryCache())
.memoryCache(new LruMemoryCache(2 * 1024 * 1024))
.memoryCacheSize(2 * 1024 * 1024).memoryCacheSizePercentage(13) // default
.threadPoolSize(2).writeDebugLogs().build();
ImageLoader.getInstance().init(config);
}
/**
* 获取图片异步加载ImageLoader对象
*
* @return
*/
public static ImageLoader getImageLoaderIntance() {
if (iamgeLoader == null) {
iamgeLoader = ImageLoader.getInstance();
}
return iamgeLoader;
}
在初始化下载器时可以根据自己的需求设置缓存位置以及其他设置。
options = new DisplayImageOptions.Builder().cacheInMemory(false)
.cacheOnDisc(true)
// 注意:compete_loading_default 在下次迭代中删除
.showStubImage(R.drawable.club_more_activity_head)
// 设置图片下载期间显示的图片
.showImageForEmptyUri(R.drawable.club_more_activity_head)
// 设置图片uri为空时显示的图片
.showImageOnFail(R.drawable.club_more_activity_head)
// 设置图片加载或解码转换失败时显示的图片
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.imageScaleType(ImageScaleType.EXACTLY).build();
try {
iv_coin.setVisibility(View.VISIBLE);
imageLoader.displayImage(logo, iv_coin, options);
} catch (Exception e) {
e.printStackTrace();
}
ImageLoader的使用不是道长说的重点,这里也就简单说一下ImageLoader的使用。
我们可以看到ImageLoader的实例获取是单例模式,并且添加了通信安全机制防止图片加载成功之前再次创建实例。
public static ImageLoader getInstance() {
if(instance == null) {
Class var0 = ImageLoader.class;
synchronized(ImageLoader.class) {
if(instance == null) {
instance = new ImageLoader();
}
}
}
return instance;
}
构造器没有什么可以说的,就是一些参数设置。
public Builder() {
this.imageScaleType = ImageScaleType.IN_SAMPLE_POWER_OF_2;
this.decodingOptions = new Options();
this.delayBeforeLoading = 0;
this.considerExifParams = false;
this.extraForDownloader = null;
this.preProcessor = null;
this.postProcessor = null;
this.displayer = DefaultConfigurationFactory.createBitmapDisplayer();
this.handler = null;
this.isSyncLoading = false;
this.decodingOptions.inPurgeable = true;
this.decodingOptions.inInputShareable = true;
}
public void displayImage(String uri, ImageView imageView, DisplayImageOptions options) {
this.displayImage(uri, (ImageAware)(new ImageViewAware(imageView)), options, (ImageLoadingListener)null, (ImageLoadingProgressListener)null);
}
public void displayImage(String uri, ImageAware imageAware) {
this.displayImage(uri, (ImageAware)imageAware, (DisplayImageOptions)null, (ImageLoadingListener)null, (ImageLoadingProgressListener)null);
}
public void displayImage(String uri, ImageAware imageAware, ImageLoadingListener listener) {
this.displayImage(uri, (ImageAware)imageAware, (DisplayImageOptions)null, listener, (ImageLoadingProgressListener)null);
}
public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options) {
this.displayImage(uri, (ImageAware)imageAware, options, (ImageLoadingListener)null, (ImageLoadingProgressListener)null);
}
public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options, ImageLoadingListener listener) {
this.displayImage(uri, (ImageAware)imageAware, options, listener, (ImageLoadingProgressListener)null);
}
public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options, ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {
this.checkConfiguration();
if(imageAware == null) {
throw new IllegalArgumentException("Wrong arguments were passed to displayImage() method (ImageView reference must not be null)");
} else {
if(listener == null) {
listener = this.emptyListener;
}
if(options == null) {
options = this.configuration.defaultDisplayImageOptions;
}
if(TextUtils.isEmpty(uri)) {
this.engine.cancelDisplayTaskFor(imageAware);
listener.onLoadingStarted(uri, imageAware.getWrappedView());
if(options.shouldShowImageForEmptyUri()) {
imageAware.setImageDrawable(options.getImageForEmptyUri(this.configuration.resources));
} else {
imageAware.setImageDrawable((Drawable)null);
}
listener.onLoadingComplete(uri, imageAware.getWrappedView(), (Bitmap)null);
} else {
ImageSize targetSize = ImageSizeUtils.defineTargetSizeForView(imageAware, this.configuration.getMaxImageSize());
String memoryCacheKey = MemoryCacheUtil.generateKey(uri, targetSize);
this.engine.prepareDisplayTaskFor(imageAware, memoryCacheKey);
listener.onLoadingStarted(uri, imageAware.getWrappedView());
Bitmap bmp = (Bitmap)this.configuration.memoryCache.get(memoryCacheKey);
ImageLoadingInfo imageLoadingInfo;
if(bmp != null && !bmp.isRecycled()) {
if(this.configuration.writeLogs) {
L.d("Load image from memory cache [%s]", new Object[]{memoryCacheKey});
}
if(options.shouldPostProcess()) {
imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey, options, listener, progressListener, this.engine.getLockForUri(uri));
ProcessAndDisplayImageTask displayTask1 = new ProcessAndDisplayImageTask(this.engine, bmp, imageLoadingInfo, options.getHandler());
if(options.isSyncLoading()) {
displayTask1.run();
} else {
this.engine.submit(displayTask1);
}
} else {
options.getDisplayer().display(bmp, imageAware, LoadedFrom.MEMORY_CACHE);
listener.onLoadingComplete(uri, imageAware.getWrappedView(), bmp);
}
} else {
if(options.shouldShowImageOnLoading()) {
imageAware.setImageDrawable(options.getImageOnLoading(this.configuration.resources));
} else if(options.isResetViewBeforeLoading()) {
imageAware.setImageDrawable((Drawable)null);
}
imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey, options, listener, progressListener, this.engine.getLockForUri(uri));
LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(this.engine, imageLoadingInfo, options.getHandler());
if(options.isSyncLoading()) {
displayTask.run();
} else {
this.engine.submit(displayTask);
}
}
}
}
}
public void displayImage(String uri, ImageView imageView) {
this.displayImage(uri, (ImageAware)(new ImageViewAware(imageView)), (DisplayImageOptions)null, (ImageLoadingListener)null, (ImageLoadingProgressListener)null);
}
public void displayImage(String uri, ImageView imageView, DisplayImageOptions options) {
this.displayImage(uri, (ImageAware)(new ImageViewAware(imageView)), options, (ImageLoadingListener)null, (ImageLoadingProgressListener)null);
}
public void displayImage(String uri, ImageView imageView, ImageLoadingListener listener) {
this.displayImage(uri, (ImageAware)(new ImageViewAware(imageView)), (DisplayImageOptions)null, listener, (ImageLoadingProgressListener)null);
}
public void displayImage(String uri, ImageView imageView, DisplayImageOptions options, ImageLoadingListener listener) {
this.displayImage(uri, (ImageView)imageView, options, listener, (ImageLoadingProgressListener)null);
}
public void displayImage(String uri, ImageView imageView, DisplayImageOptions options, ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {
this.displayImage(uri, (ImageAware)(new ImageViewAware(imageView)), options, listener, progressListener);
}
ImageLoader作为一个成熟的图片加在框架不可能只有这么一种加载方式。
public void loadImage(String uri, ImageLoadingListener listener) {
this.loadImage(uri, (ImageSize)null, (DisplayImageOptions)null, listener, (ImageLoadingProgressListener)null);
}
public void loadImage(String uri, ImageSize targetImageSize, ImageLoadingListener listener) {
this.loadImage(uri, targetImageSize, (DisplayImageOptions)null, listener, (ImageLoadingProgressListener)null);
}
public void loadImage(String uri, DisplayImageOptions options, ImageLoadingListener listener) {
this.loadImage(uri, (ImageSize)null, options, listener, (ImageLoadingProgressListener)null);
}
public void loadImage(String uri, ImageSize targetImageSize, DisplayImageOptions options, ImageLoadingListener listener) {
this.loadImage(uri, targetImageSize, options, listener, (ImageLoadingProgressListener)null);
}
public void loadImage(String uri, ImageSize targetImageSize, DisplayImageOptions options, ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {
this.checkConfiguration();
if(targetImageSize == null) {
targetImageSize = this.configuration.getMaxImageSize();
}
if(options == null) {
options = this.configuration.defaultDisplayImageOptions;
}
ImageNonViewAware imageAware = new ImageNonViewAware(uri, targetImageSize, ViewScaleType.CROP);
this.displayImage(uri, (ImageAware)imageAware, options, listener, progressListener);
}
public Bitmap loadImageSync(String uri) {
return this.loadImageSync(uri, (ImageSize)null, (DisplayImageOptions)null);
}
public Bitmap loadImageSync(String uri, DisplayImageOptions options) {
return this.loadImageSync(uri, (ImageSize)null, options);
}
public Bitmap loadImageSync(String uri, ImageSize targetImageSize) {
return this.loadImageSync(uri, targetImageSize, (DisplayImageOptions)null);
}
public Bitmap loadImageSync(String uri, ImageSize targetImageSize, DisplayImageOptions options) {
if(options == null) {
options = this.configuration.defaultDisplayImageOptions;
}
options = (new Builder()).cloneFrom(options).syncLoading(true).build();
SyncImageLoadingListener listener = new SyncImageLoadingListener();
this.loadImage(uri, targetImageSize, options, listener);
return listener.getLoadedBitmap();
}
大家可以看到加载方式三(loadImageSync)有这样一行代码:
this.loadImage(uri, targetImageSize, options, listener);
这一行代码调用了加载方式二(loadImage),也就是说加载方式三(loadImageSync)是通过调用加载方式二(loadImage)实现的。而我们再看加载方式二(loadImage)的实现方式。在加载方式二(loadImage)中发现这么一行代码:
this.displayImage(uri, (ImageAware)imageAware, options, listener, progressListener);
到这里我们就知道了ImageLoader加载图片最终实现方式都是通过调用displayImage()这个方法实现的。
咱们回头看一下displayImage()这个方法的实现:
public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options, ImageLoadingListener listener, ImageLoadingProgressListener progressListener){}
uri - 加载图片的路径
imageAware - 图片的装载容器
optins - 图片的加载器
listener - 图片的加载监听方法
progressListener - 图片的加载进度监听方法
加载图片的路径(uri)咱们就不多说了,咱们先看一下图片的装载容器(imageAware):
public interface ImageAware {
int getWidth();
int getHeight();
ViewScaleType getScaleType();
View getWrappedView();
boolean isCollected();
int getId();
boolean setImageDrawable(Drawable var1);
boolean setImageBitmap(Bitmap var1);
}
我们看到ImageAware是一个接口,接口中含有一些属性和方法,有两个类(ImageViewAware、ImageNonViewAware)实现了ImageAware接口。这里我们就不贴这两个类的代码了。
图片加载器(optins)咱们也不说了,就是一些参数的设置和初始化。图片的加载监听方法(listener)的代码如下:
public interface ImageLoadingListener {
void onLoadingStarted(String var1, View var2);
void onLoadingFailed(String var1, View var2, FailReason var3);
void onLoadingComplete(String var1, View var2, Bitmap var3);
void onLoadingCancelled(String var1, View var2);
}
我们看到这个接口有四个方法,代表加载图片的四种状态:started、failed、complete、cancelled。
图片的加载进度监听方法(progressListener)的代码如下:
public interface ImageLoadingProgressListener {
void onProgressUpdate(String var1, View var2, int var3, int var4);
}
其实么有什么好说的,就是返回加载进度。
public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options, ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {
this.checkConfiguration();
if(imageAware == null) {
throw new IllegalArgumentException("Wrong arguments were passed to displayImage() method (ImageView reference must not be null)");
} else {
if(listener == null) {
listener = this.emptyListener;
}
if(options == null) {
options = this.configuration.defaultDisplayImageOptions;
}
……
}
}
我们可以看到当imageAware为null时直接抛异常,而listener和options为null时直接调用默认设置。然后咱们接着往下看,先看一下uri为null时的一些处理:
if(TextUtils.isEmpty(uri)) {
this.engine.cancelDisplayTaskFor(imageAware);
listener.onLoadingStarted(uri, imageAware.getWrappedView());
if(options.shouldShowImageForEmptyUri()) {
imageAware.setImageDrawable(options.getImageForEmptyUri(this.configuration.resources));
} else {
imageAware.setImageDrawable((Drawable)null);
}
listener.onLoadingComplete(uri, imageAware.getWrappedView(), (Bitmap)null);
} else {
……
}
当uri为null时,先调用了cancelDisplayTaskFor()取消下载图片任务,源码如下:
void cancelDisplayTaskFor(ImageAware imageAware) {
this.cacheKeysForImageAwares.remove(Integer.valueOf(imageAware.getId()));
}
这里出现了engine,engine是ImageLoader的核心,关于engine咱么等一下再说。
然后调用了listener.onLoadingStarted()用来实现监听,然后判断在uri为null时是否显示默认图片。然后调用listener.onLoadingComplete()用来实现监听。
然后咱们再看一下uri不为null时的源码:
ImageSize targetSize = ImageSizeUtils.defineTargetSizeForView(imageAware, this.configuration.getMaxImageSize());
String memoryCacheKey = MemoryCacheUtil.generateKey(uri, targetSize);
this.engine.prepareDisplayTaskFor(imageAware, memoryCacheKey);
listener.onLoadingStarted(uri, imageAware.getWrappedView());
Bitmap bmp = (Bitmap)this.configuration.memoryCache.get(memoryCacheKey);
ImageLoadingInfo imageLoadingInfo;
if(bmp != null && !bmp.isRecycled()) {
if(this.configuration.writeLogs) {
L.d("Load image from memory cache [%s]", new Object[]{memoryCacheKey});
}
if(options.shouldPostProcess()) {
imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey, options, listener, progressListener, this.engine.getLockForUri(uri));
ProcessAndDisplayImageTask displayTask1 = new ProcessAndDisplayImageTask(this.engine, bmp, imageLoadingInfo, options.getHandler());
if(options.isSyncLoading()) {
displayTask1.run();
} else {
this.engine.submit(displayTask1);
}
} else {
options.getDisplayer().display(bmp, imageAware, LoadedFrom.MEMORY_CACHE);
listener.onLoadingComplete(uri, imageAware.getWrappedView(), bmp);
}
} else {
if(options.shouldShowImageOnLoading()) {
imageAware.setImageDrawable(options.getImageOnLoading(this.configuration.resources));
} else if(options.isResetViewBeforeLoading()) {
imageAware.setImageDrawable((Drawable)null);
}
imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey, options, listener, progressListener, this.engine.getLockForUri(uri));
LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(this.engine, imageLoadingInfo, options.getHandler());
if(options.isSyncLoading()) {
displayTask.run();
} else {
this.engine.submit(displayTask);
}
}
第一行代码就是测量控件的宽高并以实体的形式返回。
第二行代码就是拼接缓存路径。
第三行代码就是添加下载任务。
第四行代码就是调用接口,告诉加载状态变为started。
第五行代码就是获取缓存中的图片。
……
这里咱们要说一下ImageLoader的缓存,顶级接口如下:
public interface MemoryCacheAware {
boolean put(K var1, V var2);
V get(K var1);
void remove(K var1);
Collection keys();
void clear();
}
FuzzyKeyMemoryCache - 按照类的注释,这个类是框架内部使用的
LimitedAgeMemoryCache - 当 bitmap加入缓存中的时间超过我们设定的值,将其删除
LruMemoryCache - 这个类就是这个开源框架默认的内存缓存类,缓存的是bitmap的强引用
也就是说有四种缓存方式,当然baseMemoryCache还有一些子类对baseMemoryCache的功能进行了扩展。咱们这里就不介绍这么详细了,如果有时间在详细说一下。
然后咱们接着往下看,这里有一个判断,当bmp != null 并且 !bmp.isRecycled()时,就会有一种操作:重新下载还是加载缓存;反之,就直接下载图片。当然这里还会有一些其他操作,比如,加载方式是不是异步,加载中是不是展示默认图片等等。
imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey, options, listener, progressListener, this.engine.getLockForUri(uri));
LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(this.engine, imageLoadingInfo, options.getHandler());
if(options.isSyncLoading()) {
displayTask.run();
} else {
this.engine.submit(displayTask);
}
咱们看到加载图片有两种方式,异步加载和同步加载。咱们先看一下异步加载,异步加载调用的代码displayTask.run()。源码如下:
public void run() {
if(!this.waitIfPaused()) {
if(!this.delayIfNeed()) {
ReentrantLock loadFromUriLock = this.imageLoadingInfo.loadFromUriLock;
this.log("Start display image task [%s]");
if(loadFromUriLock.isLocked()) {
this.log("Image already is loading. Waiting... [%s]");
}
loadFromUriLock.lock();
Bitmap bmp;
label132: {
try {
this.checkTaskNotActual();
bmp = (Bitmap)this.configuration.memoryCache.get(this.memoryCacheKey);
if(bmp == null) {
bmp = this.tryLoadBitmap();
if(bmp == null) {
return;
}
this.checkTaskNotActual();
this.checkTaskInterrupted();
if(this.options.shouldPreProcess()) {
this.log("PreProcess image before caching in memory [%s]");
bmp = this.options.getPreProcessor().process(bmp);
if(bmp == null) {
L.e("Pre-processor returned null [%s]", new Object[]{this.memoryCacheKey});
}
}
if(bmp != null && this.options.isCacheInMemory()) {
this.log("Cache image in memory [%s]");
this.configuration.memoryCache.put(this.memoryCacheKey, bmp);
}
} else {
this.loadedFrom = LoadedFrom.MEMORY_CACHE;
this.log("...Get cached bitmap from memory after waiting. [%s]");
}
if(bmp != null && this.options.shouldPostProcess()) {
this.log("PostProcess image before displaying [%s]");
bmp = this.options.getPostProcessor().process(bmp);
if(bmp == null) {
L.e("Post-processor returned null [%s]", new Object[]{this.memoryCacheKey});
}
}
this.checkTaskNotActual();
this.checkTaskInterrupted();
break label132;
} catch (LoadAndDisplayImageTask.TaskCancelledException var7) {
this.fireCancelEvent();
} finally {
loadFromUriLock.unlock();
}
return;
}
DisplayBitmapTask displayBitmapTask = new DisplayBitmapTask(bmp, this.imageLoadingInfo, this.engine, this.loadedFrom);
displayBitmapTask.setLoggingEnabled(this.writeLogs);
if(this.options.isSyncLoading()) {
displayBitmapTask.run();
} else {
this.handler.post(displayBitmapTask);
}
}
}
}
其中代码bmp = this.tryLoadBitmap();为加载图片方法,实现如下:
private Bitmap tryLoadBitmap() throws LoadAndDisplayImageTask.TaskCancelledException {
File imageFile = this.getImageFileInDiscCache();
Bitmap bitmap = null;
try {
String e = Scheme.FILE.wrap(imageFile.getAbsolutePath());
if(imageFile.exists()) {
this.log("Load image from disc cache [%s]");
this.loadedFrom = LoadedFrom.DISC_CACHE;
this.checkTaskNotActual();
bitmap = this.decodeImage(e);
}
if(bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
this.log("Load image from network [%s]");
this.loadedFrom = LoadedFrom.NETWORK;
String imageUriForDecoding = this.options.isCacheOnDisc() && this.tryCacheImageOnDisc(imageFile)?e:this.uri;
this.checkTaskNotActual();
bitmap = this.decodeImage(imageUriForDecoding);
if(bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
this.fireFailEvent(FailType.DECODING_ERROR, (Throwable)null);
}
}
} catch (IllegalStateException var5) {
this.fireFailEvent(FailType.NETWORK_DENIED, (Throwable)null);
} catch (LoadAndDisplayImageTask.TaskCancelledException var6) {
throw var6;
} catch (IOException var7) {
L.e(var7);
this.fireFailEvent(FailType.IO_ERROR, var7);
if(imageFile.exists()) {
imageFile.delete();
}
} catch (OutOfMemoryError var8) {
L.e(var8);
this.fireFailEvent(FailType.OUT_OF_MEMORY, var8);
} catch (Throwable var9) {
L.e(var9);
this.fireFailEvent(FailType.UNKNOWN, var9);
}
return bitmap;
}
并且进行了缓存处理:
if(bmp != null && this.options.isCacheInMemory()) {
this.log("Cache image in memory [%s]");
this.configuration.memoryCache.put(this.memoryCacheKey, bmp);
}
然后我们最后又调用了displayBitmapTask.run()装载图片,源码如下:
public void run() {
if(this.imageAware.isCollected()) {
if(this.loggingEnabled) {
L.d("ImageAware was collected by GC. Task is cancelled. [%s]", new Object[]{this.memoryCacheKey});
}
this.listener.onLoadingCancelled(this.imageUri, this.imageAware.getWrappedView());
} else if(this.isViewWasReused()) {
if(this.loggingEnabled) {
L.d("ImageAware is reused for another image. Task is cancelled. [%s]", new Object[]{this.memoryCacheKey});
}
this.listener.onLoadingCancelled(this.imageUri, this.imageAware.getWrappedView());
} else {
if(this.loggingEnabled) {
L.d("Display image in ImageAware (loaded from %1$s) [%2$s]", new Object[]{this.loadedFrom, this.memoryCacheKey});
}
this.displayer.display(this.bitmap, this.imageAware, this.loadedFrom);
this.listener.onLoadingComplete(this.imageUri, this.imageAware.getWrappedView(), this.bitmap);
this.engine.cancelDisplayTaskFor(this.imageAware);
}
}
我们看this.displayer.display(this.bitmap, this.imageAware, this.loadedFrom);这行代码,只是把bitmap装载到imageAware上,咱们追踪一下源码:
获取displayer实例:
this.displayer = imageLoadingInfo.options.getDisplayer();
DisplayImageOptions.Builder()中的构造代码调用:
this.displayer = DefaultConfigurationFactory.createBitmapDisplayer();
调用DefaultConfigurationFactory中方法:
public static BitmapDisplayer createBitmapDisplayer() {
return new SimpleBitmapDisplayer();
}
SimpleBitmapDisplayer中方法实现:
public void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom) {
imageAware.setImageBitmap(bitmap);
}
异步加载图片说完了,咱们再说说同步加载图片,其实创建任务是和异步相同的,只是调用不同,源码如下:
void submit(final LoadAndDisplayImageTask task) {
this.taskDistributor.execute(new Runnable() {
public void run() {
boolean isImageCachedOnDisc = ImageLoaderEngine.this.configuration.discCache.get(task.getLoadingUri()).exists();
ImageLoaderEngine.this.initExecutorsIfNeed();
if(isImageCachedOnDisc) {
ImageLoaderEngine.this.taskExecutorForCachedImages.execute(task);
} else {
ImageLoaderEngine.this.taskExecutor.execute(task);
}
}
});
}
好了,到了这里咱们算是把ImageLoader的整体流程梳理了一遍,其他的就不说了,等有时间了再说一下ImageLoader的缓存。希望这篇博客能够为你提供一些帮助。