Android-Universal-Image-Loader是一个开源的UI组件程序,该项目的目的是提供一个可重复使用的仪器为异步图像加载,缓存和显示。
权限:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

ImageLoaderConfiguration是针对图片缓存的全局配置,主要有线程类、缓存大小、磁盘大小、图片下载与解析、日志方面的配置

ImageLoader是具体下载图片,缓存图片,显示图片的具体执行类,它有两个具体的方法displayImage(...)、loadImage(...),但是其实最终他们的实现都是displayImage(...)。

DisplayImageOptions用于指导每一个Imageloader根据网络图片的状态(空白、下载错误、正在下载)显示对应的图片,是否将缓存加载到磁盘上,下载完后对图片进行怎么样的处理。

public class ImageLoadUtil {
private static ImageLoadUtil imageLoadUtil = null;
private ImageLoaderConfiguration config = null;
private DisplayImageOptions options = null;
private ImageLoadUtil(Context context){
options = new DisplayImageOptions.Builder()
//.showImageOnLoading(R.drawable.ic_launcher) //设置图片在下载期间显示的图片
//.showImageForEmptyUri(R.drawable.ic_launcher)//设置图片Uri为空或是错误的时候显示的图片
//.showImageOnFail(R.drawable.ic_launcher) //设置图片加载/解码过程中错误时候显示的图片
.cacheInMemory(true)//设置下载的图片是否缓存在内存中
.cacheOnDisc(true)//设置下载的图片是否缓存在SD卡中
.considerExifParams(true) //是否考虑JPEG图像EXIF参数(旋转,翻转)
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED)//设置图片以如何的编码方式显示
.bitmapConfig(Bitmap.Config.RGB_565)//设置图片的解码类型//
//.delayBeforeLoading(int delayInMillis)//int delayInMillis为你设置的下载前的延迟时间
//设置图片加入缓存前,对bitmap进行设置
//.preProcessor(BitmapProcessor preProcessor)
.resetViewBeforeLoading(true)//设置图片在下载前是否重置,复位
.displayer(new RoundedBitmapDisplayer(20))//是否设置为圆角,弧度为多少
.displayer(new FadeInBitmapDisplayer(100))//是否图片加载好后渐入的动画时间
.build();//构建完成 config = new ImageLoaderConfiguration.Builder(
context).threadPriority(Thread.NORM_PRIORITY - 2)// 加载图片的线程数
.denyCacheImageMultipleSizesInMemory() // 解码图像的大尺寸将在内存中缓存先前解码图像的小尺寸。
.discCacheFileNameGenerator(new Md5FileNameGenerator())// 设置磁盘缓存文件名称
.tasksProcessingOrder(QueueProcessingType.LIFO)// 设置加载显示图片队列进程
.writeDebugLogs() // Remove for release app
.discCache(new UnlimitedDiscCache(new File(FileCacheUtil.getPicCacheDir()))) // 文件缓存目录
.defaultDisplayImageOptions(options)// 创建配置过得DisplayImageOption对象
.build();
/*config = new ImageLoaderConfiguration.Builder(context)
.threadPriority(Thread.NORM_PRIORITY - 2)
.denyCacheImageMultipleSizesInMemory()
.diskCacheFileNameGenerator(new Md5FileNameGenerator())
.tasksProcessingOrder(QueueProcessingType.LIFO)
.writeDebugLogs()
.build();*/
ImageLoader.getInstance().init(config);
} public static ImageLoadUtil init(Context context){
if (imageLoadUtil == null) {
imageLoadUtil = new ImageLoadUtil(context);
}
return imageLoadUtil;
}
}

首先分析:ImageLoaderConfiguration

1
因为使用时使用到ImageLoaderConfiguration的构造方法,所以先看ImageLoaderConfiguration的构造方法:

//设置内存缓存的选项,用于将图片将图片解析成最大指定宽高的大小的图片进行缓存(缓存在内存中的图片宽高)。
memoryCacheExtraOptions(int maxImageWidthForMemoryCache, int maxImageHeightForMemoryCache) //设置磁盘缓存的选项,maxImageWidthForDiskCache()和maxImageHeightForDiskCache()缓存在硬盘里面图片最大尺寸。 diskCacheExtraOptions(int maxImageWidthForDiskCache, int maxImageHeightForDiskCache, BitmapProcessor processorForDiskCache) //设置自定义加载和显示任务的线程池
taskExecutor(Executor executor) //设置自定义显示任务的线程池
taskExecutorForCachedImages(Executor executorForCachedImages) //设置图片显示任务的线程池大小
threadPoolSize(int threadPoolSize) //设置线程的优先级
threadPriority(int threadPriority) //设置拒绝缓存一张图片的多个尺寸
denyCacheImageMultipleSizesInMemory() //设置加载和显示图片任务队列的类型
tasksProcessingOrder(QueueProcessingType tasksProcessingType) //设置最大内存缓存字节数
memoryCacheSize(int memoryCacheSize) //设置最大内存缓存所占app可用内存的百分比
memoryCacheSizePercentage(int availableMemoryPercent) //设置内存缓存算法
memoryCache(MemoryCache memoryCache) //设置最大磁盘缓存字节数
diskCacheSize(int maxCacheSize) //设置在磁盘缓存文件夹下最多文件数
diskCacheFileCount(int maxFileCount) //设置磁盘缓存文件生成的命名规则
diskCacheFileNameGenerator(FileNameGenerator fileNameGenerator) //设置磁盘缓存
diskCache(DiskCache diskCache) //设置下载图片的工具
imageDownloader(ImageDownloader imageDownloader) //设置decode出bitmap的工具
imageDecoder(ImageDecoder imageDecoder) //设置默认的DisplayImageOptions
defaultDisplayImageOptions(DisplayImageOptions defaultDisplayImageOptions) //log信息
writeDebugLogs() public ImageLoaderConfiguration build() {
initEmptyFieldsWithDefaultValues();
return new ImageLoaderConfiguration(this);
} 在分析DisplayImageOptions(图片加载过程中各种情况的处理): //设置图片加载过程中显示的图片
showImageOnLoading(int imageRes) //设置空URI显示的图片
showImageForEmptyUri(int imageRes) //设置发生错误显示的图片
showImageOnFail(int imageRes) //设置图片加载前是否重置
resetViewBeforeLoading(boolean resetViewBeforeLoading) //设置是否将图片缓存在内存里
cacheInMemory(boolean cacheInMemory) //设置是否将图片缓存在磁盘上
cacheOnDisk(boolean cacheOnDisk) //设置图片缩放的类型
imageScaleType(ImageScaleType imageScaleType) //设置Bitmap.Config
bitmapConfig(Bitmap.Config bitmapConfig) //设置图片解码的选项
decodingOptions(Options decodingOptions) //设置加载任务前的延迟
delayBeforeLoading(int delayInMillis) //设置下载时额外的对象
extraForDownloader(Object extra) //设置是否考虑EXIF信息
considerExifParams(boolean considerExifParams) //设置内存缓存bitmap对象前的处理
preProcessor(BitmapProcessor preProcessor) //设置内存缓存bitmap对象后的处理
postProcessor(BitmapProcessor postProcessor) //设置图片的显示方式
displayer(BitmapDisplayer displayer) //true是直接调用LoadAndDisplayImageTask对象的run方法,false是放到线程池里面执行,默认false
syncLoading(boolean isSyncLoading) //设置显示图片和触发ImageLoadingListener事件的自定义Handler对象
handler(Handler handler)

ImageLoader使用的是单利模式:

在展示的时候调用的是:displayImage和loadImage两个方法:
分析displayImage:

public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options,
ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {
//检查UIL的配置是否被初始化
checkConfiguration();
if (imageAware == null) {
throw new IllegalArgumentException(ERROR_WRONG_ARGUMENTS);
}
if (listener == null) {
listener = emptyListener;
}
if (options == null) {
options = configuration.defaultDisplayImageOptions;
} if (TextUtils.isEmpty(uri)) {
engine.cancelDisplayTaskFor(imageAware);
listener.onLoadingStarted(uri, imageAware.getWrappedView());
//没有图片时,显示displayImage传过来的图片不存在情况下的图片
if (options.shouldShowImageForEmptyUri()) {
imageAware.setImageDrawable(options.getImageForEmptyUri(configuration.resources));
} else {
imageAware.setImageDrawable(null);
}
listener.onLoadingComplete(uri, imageAware.getWrappedView(), null);
return;
}

//计算Bitmap的大小,以便后面解析图片时用

ImageSize targetSize = ImageSizeUtils.defineTargetSizeForView(imageAware, configuration.getMaxImageSize());
//内存缓存的名称
String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize);
engine.prepareDisplayTaskFor(imageAware, memoryCacheKey); listener.onLoadingStarted(uri, imageAware.getWrappedView());
//Bitmap是否缓存在内存?
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);
}
}
}

再往下分析LoadAndDisplayImageTask
根据uri看看磁盘中是不是已经缓存了这个文件,如果有了,调用decodeImage方法,将图片文件decode成bitmap对象,若文件不存在,调用tryCacheImageOnDisk()方法去下载并缓存图片到本地磁盘,再通过decodeImage方法将图片文件decode成bitmap对象

private Bitmap tryLoadBitmap() throws TaskCancelledException {
Bitmap bitmap = null;
try {
//尝试从磁盘缓存中读取Bitmap
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;
//将网络里面的图片缓存到SD卡里面
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;
} tryCacheImageOnDisk()里面是: loaded = downloadImage(); private boolean downloadImage() throws IOException {
//获取图片输入流
InputStream is = getDownloader().getStream(uri, options.getExtraForDownloader());
if (is == null) {
L.e(ERROR_NO_IMAGE_STREAM, memoryCacheKey);
return false;
} else {
try {
//不为null,进行SD卡保存
return configuration.diskCache.save(uri, is, this);
} finally {
IoUtils.closeSilently(is);
}
}
}

configuration.diskCache.save(uri, is, this),接下来看save保存图片到SD卡的程序;它先是生成一个后缀名.tmp的临时文件,通过downloader得到的输入流imageStream拷贝到OutputStream中, finally中将临时文件tmpFile重命名回imageFile,并将tmpFile删除掉, 如果这些实现都没出什么问题,就reutrn一个true, 告诉别人,我save成功了:

public boolean save(String imageUri, InputStream imageStream, IoUtils.CopyListener listener) throws IOException {
File imageFile = getFile(imageUri);
//tmp的临时文件
File tmpFile = new File(imageFile.getAbsolutePath() + TEMP_IMAGE_POSTFIX);
boolean loaded = false;
try {
OutputStream os = new BufferedOutputStream(new FileOutputStream(tmpFile), bufferSize);
try {
loaded = IoUtils.copyStream(imageStream, os, listener, bufferSize);
} finally {
//将临时文件tmpFile重命名回imageFile,并将tmpFile删除掉
IoUtils.closeSilently(os);
}
} finally {
if (loaded && !tmpFile.renameTo(imageFile)) {
loaded = false;
}
if (!loaded) {
tmpFile.delete();
}
}
//true save成功
//false save失败
return loaded;
}

http://www.cnblogs.com/kissazi2/p/3901369.html

Universal-Image-Loader分析:的更多相关文章

  1. android universal image loader 缓冲原理详解

    1. 功能介绍 1.1 Android Universal Image Loader Android Universal Image Loader 是一个强大的.可高度定制的图片缓存,本文简称为UIL ...

  2. universal image loader自己使用的一些感受

    1.全局入口的Application定义初始化: ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Build ...

  3. 【译】UNIVERSAL IMAGE LOADER. PART 3---ImageLoader详解

    在之前的文章,我们重点讲了Android-Universal-Image-Loader的三个主要组件,现在我们终于可以开始使用它了. Android-Universal-Image-Loader有四个 ...

  4. Android中Universal Image Loader开源框架的简单使用

    UIL (Universal Image Loader)aims to provide a powerful, flexible and highly customizable instrument ...

  5. universal image loader在listview/gridview中滚动时重复加载图片的问题及解决方法

    在listview/gridview中使用UIL来display每个item的图片,当图片数量较多需要滑动滚动时会出现卡顿,而且加载过的图片再次上翻后依然会重复加载(显示设置好的加载中图片) 最近在使 ...

  6. 【Android应用开发】 Universal Image Loader ( 使用简介 | 示例代码解析 )

    作者 : 韩曙亮 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/50824912 相关地址介绍 : -- Universal I ...

  7. 开源项目Universal Image Loader for Android 说明文档 (1) 简介

     When developing applications for Android, one often facesthe problem of displaying some graphical ...

  8. 开源项目Universal Image Loader for Android 说明文档 (1) 简单介绍

     When developing applications for Android, one often facesthe problem of displaying some graphical ...

  9. 9 loader - 分析webpack调用第三方loader的过程

    注意:webpack处理第三方文件类型的过程: 1.发现这个要处理的文件不是JS文件,然后就去配置文件中,查找有没有对应的第三方loader规则 2.如果能找到对应的规则,就会调用对应的loader处 ...

  10. 【译】UNIVERSAL IMAGE LOADER.PART 2---ImageLoaderConfiguration详解

    ImageLoader类中包含了所有操作.他是一个单例,为了获取它的一个单一实例,你需要调用getInstance()方法.在使用ImageLoader来显示图片之前,你需要初始化它的配置-Image ...

随机推荐

  1. 365DirMon(文件夹监视专家) v2.8绿色免费版

    软件名称:365DirMon(文件夹监视专家)软件语言: 简体中文授权方式: 免费软件运行环境: Win 32位/64位软件大小: 1.6M 图片预览: 软件简介:365DirMon 是一可以监控磁盘 ...

  2. 项目管理实践【六】自动同步数据库【Using Visual Studio with Source Control System to synchronize database automatically】

    在上一篇项目管理实践[五]自动编译和发布网站中,我们讲解了如何使用MSBuild+Robocopy+WebDeployment来自动编译和部署网站,今天,我们来看一下,如何使用MSBuild +SVN ...

  3. jQuery(1)——了解jQuery

    jQuery 终于开始了jQuery的学习了,好开心,虽然感觉JavaScript并没有学好,尴尬.木事,咋们慢慢来.fighting [jQuery简介] jQuery是继Prototype之后又一 ...

  4. 用shell获得hadoop中mapreduce任务运行结果的状态

    在近期的工作中,我需要用脚本来运行mapreduce,并且要判断运行的结果,根据结果来做下一步的动作. 开始我想到shell中获得上一条命令运行结果的方法,即判断"$?"的值 if ...

  5. Struts2--课程笔记3

    获取ServletAPI: 第一种方式: //在request域中放入属性req,暂且认为getContext()获取的是request域空间,但实际不是        ActionContext.g ...

  6. nodejs【伪】入门教程

    声明: 本文适合白的不能再白的小白 不要被标题误导,本文不会讲nodejs基础,只是本人学习流程和资料的一个整合 如果想找一大堆教程自己看,没有电梯,自己拉到文章最下方吧   一.nodejs是什么 ...

  7. 关于Unity中的涉及到Attribute的相关概念整理(@WhiteTaken)

    这两天事情比较多,没有来得及更新,现在把我这两天看的attributes相关内容进行整理. 涉及到的相关概念包括: C#中的特性概念及用法 创建自己的特性以及通过反射访问特性 C#中的特性概念以及用法 ...

  8. Edit Individual GridView Cells in ASP.NET

    Edit individual GridView cells without putting the entire row into edit mode.Examples using the SqlD ...

  9. Codeforces Round #350 (Div. 2)_D2 - Magic Powder - 2

    D2. Magic Powder - 2 time limit per test 1 second memory limit per test 256 megabytes input standard ...

  10. centos 命令行 连接无线网卡

    ifconfig wlan0 up 1 ifconfig wlan0 iwlist wlan0 scan wpa_passphrase naizhongnai naizhong >> /e ...