您的位置:首页 > 移动开发 > Android开发

Android-Universal-Image-Loader主要功能和图片加载过程

2015-02-25 10:50 399 查看

主要功能

1.  多线程图片加载,无论是同步还是异步加载

2.  对图片加载的可以进行多种配置

3.  对每一个图片展示定制多种选项

4.  图片缓存在内存和磁盘中

5.  监听图片加载的过程

可以使用的uri例子

"http://site.com/image.png"// from Web
"file:///mnt/sdcard/image.png"// from SD card
"file:///mnt/sdcard/video.mp4"// from SD card (video thumbnail)
"content://media/external/images/media/13"// from content provider
"content://media/external/video/media/13"// from content provider (video thumbnail)
"assets://image.png"// from assets
"drawable://"+ R.drawable.img//
from drawables (non-9patch images)

图片加载过程



这张图描述了加载过程:

1.展示图片ImageLoader.class
<pre name="code" class="java">/**
* Adds display image task to execution pool. Image will be set to ImageAware when it's turn.<br />
* <b>NOTE:</b> {@link #init(ImageLoaderConfiguration)} method must be called before this method call
*
* @param uri              Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png")
* @param imageAware       {@linkplain com.nostra13.universalimageloader.core.imageaware.ImageAware Image aware view}
*                         which should display image
* @param options          {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions Options} for image
*                         decoding and displaying. If <b>null</b> - default display image options
*                         {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions)
*                         from configuration} will be used.
* @param listener         {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires
*                         events on UI thread if this method is called on UI thread.
* @param progressListener {@linkplain com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener
*                         Listener} for image loading progress. Listener fires events on UI thread if this method
*                         is called on UI thread. Caching on disk should be enabled in
*                         {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions options} to make
*                         this listener work.
* @throws IllegalStateException    if {@link #init(ImageLoaderConfiguration)} method wasn't called before
* @throws IllegalArgumentException if passed <b>imageAware</b> is null
*/
public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options,
ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {
checkConfiguration();
if (imageAware == null) {
throw new IllegalArgumentException(ERROR_WRONG_ARGUMENTS);
}
if (listener == null) {
listener = emptyListener;
}
if (options == null) {
options = configuration.defaultDisplayImageOptions;
}
/**
* 判断uri是否为空
*/
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;
}

//获取图片的大小
ImageSize targetSize = ImageSizeUtils.defineTargetSizeForView(imageAware, configuration.getMaxImageSize());
//生成存储的一个key
String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize);
engine.prepareDisplayTaskFor(imageAware, memoryCacheKey);

//发送图片加载开始消息
listener.onLoadingStarted(uri, imageAware.getWrappedView());

//判断是否内存中存在这个图片
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);
}
}
}




如果在图片在内存中就使用ProcessAndDisplayImageTask
如果在图片不在内存中就使用LoadAndDisplayImageTask

ProcessAndDisplayImageTask.class
@Override
public void run() {
L.d(LOG_POSTPROCESS_IMAGE, imageLoadingInfo.memoryCacheKey);

BitmapProcessor processor = imageLoadingInfo.options.getPostProcessor();
//处理图像
Bitmap processedBitmap = processor.process(bitmap);
//创建显示图片的任务
DisplayBitmapTask displayBitmapTask = new DisplayBitmapTask(processedBitmap, imageLoadingInfo, engine,
LoadedFrom.MEMORY_CACHE);
LoadAndDisplayImageTask.runTask(displayBitmapTask, imageLoadingInfo.options.isSyncLoading(), handler, engine);
}


LoadAndDisplayImageTask.class

@Override
public void run() {
if (waitIfPaused()) return;
if (delayIfNeed()) return;

ReentrantLock loadFromUriLock = imageLoadingInfo.loadFromUriLock;
L.d(LOG_START_DISPLAY_IMAGE_TASK, memoryCacheKey);
if (loadFromUriLock.isLocked()) {
L.d(LOG_WAITING_FOR_IMAGE_LOADED, memoryCacheKey);
}

loadFromUriLock.lock();
Bitmap bmp;
try {
//检查任务是否存在
checkTaskNotActual();
//获取内存中的图片是否存在
bmp = configuration.memoryCache.get(memoryCacheKey);
if (bmp == null || bmp.isRecycled()) {
//如果不存在或者被回收了就是尝试去加载图片
bmp = tryLoadBitmap();
if (bmp == null) return; // listener callback already was fired

checkTaskNotActual();
checkTaskInterrupted();
//是否在载入内存中进行处理
if (options.shouldPreProcess()) {
L.d(LOG_PREPROCESS_IMAGE, memoryCacheKey);
bmp = options.getPreProcessor().process(bmp);
if (bmp == null) {
L.e(ERROR_PRE_PROCESSOR_NULL, memoryCacheKey);
}
}
//在图片不为空并且需要被放入内存中
if (bmp != null && options.isCacheInMemory()) {
L.d(LOG_CACHE_IMAGE_IN_MEMORY, memoryCacheKey);
configuration.memoryCache.put(memoryCacheKey, bmp);
}
} else {
loadedFrom = LoadedFrom.MEMORY_CACHE;
L.d(LOG_GET_IMAGE_FROM_MEMORY_CACHE_AFTER_WAITING, memoryCacheKey);
}
//在显示钱是否进程处理
if (bmp != null && options.shouldPostProcess()) {
L.d(LOG_POSTPROCESS_IMAGE, memoryCacheKey);
bmp = options.getPostProcessor().process(bmp);
if (bmp == null) {
L.e(ERROR_POST_PROCESSOR_NULL, memoryCacheKey);
}
}
checkTaskNotActual();
checkTaskInterrupted();
} catch (TaskCancelledException e) {
fireCancelEvent();
return;
} finally {
loadFromUriLock.unlock();
}

DisplayBitmapTask displayBitmapTask = new DisplayBitmapTask(bmp, imageLoadingInfo, engine, loadedFrom);
runTask(displayBitmapTask, syncLoading, handler, engine);
}


private Bitmap tryLoadBitmap() throws TaskCancelledException {
Bitmap bitmap = null;
try {
//是否在磁盘中存在
File imageFile = configuration.diskCache.get(uri);
if (imageFile != null && imageFile.exists()) {
//如果存在就载入图片
L.d(LOG_LOAD_IMAGE_FROM_DISK_CACHE, memoryCacheKey);
loadedFrom = LoadedFrom.DISC_CACHE;

checkTaskNotActual();
bitmap = decodeImage(Scheme.FILE.wrap(imageFile.getAbsolutePath()));
}
if (bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
//如果没有就重远程加载图片
L.d(LOG_LOAD_IMAGE_FROM_NETWORK, memoryCacheKey);
loadedFrom = LoadedFrom.NETWORK;

String imageUriForDecoding = uri;
if (options.isCacheOnDisk() && tryCacheImageOnDisk()) {
imageFile = configuration.diskCache.get(uri);
if (imageFile != null) {
imageUriForDecoding = Scheme.FILE.wrap(imageFile.getAbsolutePath());
}
}

checkTaskNotActual();
bitmap = decodeImage(imageUriForDecoding);

if (bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
fireFailEvent(FailType.DECODING_ERROR, null);
}
}
} catch (IllegalStateException e) {
fireFailEvent(FailType.NETWORK_DENIED, null);
} catch (TaskCancelledException e) {
throw e;
} catch (IOException e) {
L.e(e);
fireFailEvent(FailType.IO_ERROR, e);
} catch (OutOfMemoryError e) {
L.e(e);
fireFailEvent(FailType.OUT_OF_MEMORY, e);
} catch (Throwable e) {
L.e(e);
fireFailEvent(FailType.UNKNOWN, e);
}
return bitmap;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: