使用方式就不说了、直接源码分析:
一、ImageLoader分析(供上层调用,提供同步、异步加载方式)
public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options,
ImageSize targetSize, ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {
//检测配置信息、相关类:ImageLoaderConfiguration
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)) {
engine.cancelDisplayTaskFor(imageAware);
listener.onLoadingStarted(uri, imageAware.getWrappedView());
if (options.shouldShowImageForEmptyUri()) {
imageAware.setImageDrawable(options.getImageForEmptyUri(configuration.resources));
} else {
imageAware.setImageDrawable(null);
}
listener.onLoadingComplete(uri, imageAware.getWrappedView(), null);
return;
}
//根据获取目标view的大小,换算出所需的内存,并加入ImageLoaderEngine类中的cacheKeysForImageAwares队列
if (targetSize == null) {
targetSize = ImageSizeUtils.defineTargetSizeForView(imageAware, configuration.getMaxImageSize());
}
String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize);
engine.prepareDisplayTaskFor(imageAware, memoryCacheKey);
//判断内存是否有缓存,若有启用ProcessAndDisplayImageTask线程加载图片
//否则使用LoadAndDisplayImageTask线程加载图片
//并提交给ImageLoaderEngine的线程池对象执行
Bitmap bmp = configuration.memoryCache.get(memoryCacheKey);
if (bmp != null && !bmp.isRecycled()) {
L.d(LOG_LOAD_IMAGE_FROM_MEMORY_CACHE, memoryCacheKey);
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 {
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 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);
}
}
二、ImageLoaderEngine分析( 三个线程池、利用ReentrantLock(重入锁)和AtomicBoolean(原子)来解决多线程访问)
private Executor taskExecutor;//加载网络图片的线程池
private Executor taskExecutorForCachedImages;//加载文件缓存和内存缓存的线程池
private Executor taskDistributor;//判断是否有文件缓存、并确定使用taskExecutor还是taskExecutorForCachedImages加载图片
三、ImageLoaderConfiguration分析( 主要是内存大小、队列请求方式、线程优先级等配置,提供三种加载方式) 1、downloader(默认网络加载、用InputStream实现)
2、networkDeniedDownloader(非网络加载)
3、slowNetworkDownloader(弱网加载、继承FilterInputStream,重写skip方法。注:因为InputStream的skip方法有最少值限制、所以当弱网下载时、可能会中断)
inputStream 源码:
public long skip(long n) throws IOException {
long remaining = n;
int nr;
if (n <= 0) {
return 0;
}
int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
byte[] skipBuffer = new byte[size];
while (remaining > 0) {
nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
if (nr < 0) {
break;
}
remaining -= nr;
}
return n - remaining;
}
FilterInputStream源码:
@Override
public long skip(long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int by_te = read();
if (by_te < 0) {
break; // we reached EOF
} else {
bytesSkipped = 1; // we read one byte
}
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
四、LoadAndDisplayImageTask分析(使用ReentrantLock重入锁来确保加载成功后不错位)
执行线程、sync true为同步、false为异步
static void runTask(Runnable r, boolean sync, Handler handler, ImageLoaderEngine engine) {
if (sync) {
r.run();
} else if (handler == null) {
engine.fireCallback(r);
} else {
handler.post(r);
}
}
五、其他
继承BitmapDisplayer实现不同的显示方式、圆角、裁剪等 cache包下提供若干个缓存方式