Universal-Image-Loader分析:
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分析:的更多相关文章
- android universal image loader 缓冲原理详解
1. 功能介绍 1.1 Android Universal Image Loader Android Universal Image Loader 是一个强大的.可高度定制的图片缓存,本文简称为UIL ...
- universal image loader自己使用的一些感受
1.全局入口的Application定义初始化: ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Build ...
- 【译】UNIVERSAL IMAGE LOADER. PART 3---ImageLoader详解
在之前的文章,我们重点讲了Android-Universal-Image-Loader的三个主要组件,现在我们终于可以开始使用它了. Android-Universal-Image-Loader有四个 ...
- Android中Universal Image Loader开源框架的简单使用
UIL (Universal Image Loader)aims to provide a powerful, flexible and highly customizable instrument ...
- universal image loader在listview/gridview中滚动时重复加载图片的问题及解决方法
在listview/gridview中使用UIL来display每个item的图片,当图片数量较多需要滑动滚动时会出现卡顿,而且加载过的图片再次上翻后依然会重复加载(显示设置好的加载中图片) 最近在使 ...
- 【Android应用开发】 Universal Image Loader ( 使用简介 | 示例代码解析 )
作者 : 韩曙亮 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/50824912 相关地址介绍 : -- Universal I ...
- 开源项目Universal Image Loader for Android 说明文档 (1) 简介
When developing applications for Android, one often facesthe problem of displaying some graphical ...
- 开源项目Universal Image Loader for Android 说明文档 (1) 简单介绍
When developing applications for Android, one often facesthe problem of displaying some graphical ...
- 9 loader - 分析webpack调用第三方loader的过程
注意:webpack处理第三方文件类型的过程: 1.发现这个要处理的文件不是JS文件,然后就去配置文件中,查找有没有对应的第三方loader规则 2.如果能找到对应的规则,就会调用对应的loader处 ...
- 【译】UNIVERSAL IMAGE LOADER.PART 2---ImageLoaderConfiguration详解
ImageLoader类中包含了所有操作.他是一个单例,为了获取它的一个单一实例,你需要调用getInstance()方法.在使用ImageLoader来显示图片之前,你需要初始化它的配置-Image ...
随机推荐
- 关于oracle数据库(4)数据类型
数据类型 字符数据类型char:固定长度字符串,最大可以存放2000字节 字符串varchar2:可变长度字符串,最大可以存放2GB数值类型数据 数字number:可以存放整数.浮点数.实数 numb ...
- oracle行转列函数
- 【2】docker 与UFW
ufw是一个主机端的iptables类防火墙配置工具. 1.查看ufw的状态:ufw status 2.如果使用UFW,需要对其进行修改才能让DOCKER工作.docker使用一个网桥来管理容器中的网 ...
- mysql 1053错误,无法启动的解决方法
mysql 1053错误,无法启动的解决方法 windows2003服务器中,服务器重启后Mysql却没有启动,手动启动服务时提示1053错误. 尝试了以下方法,终于解决. 1.在DOS命令行使用 第 ...
- nfs服务器的建立
NFS服务器的配置 一.NFS服务器端的配置,即共享发布者 (一)需启动的服务和需安装的软件 1.NFS服务器必须启动两个daemons服务:rpc.nfsd和rpc.mountd rpc.nfs ...
- ADT(abstract data types)抽象数据类型
1.What is it? An abstract data type is a set of objects together with a set of operations. 抽象数据类型是带有 ...
- while;do while;switch;break;continue
1.while: 格式:while(判断条件) { 满足条件要执行的语句 } while语句与for语句对比(小九九) 1.1 for <script>for (var i= ...
- .NET面试题目二
1.对你来说工作中最重要的是什么? 答:团队目标的实现.(这是所有公司希望员工拥有的素质) 2.为什么愿意为本公司工作? 答:因为我认为我可以与贵公司取得共同的发展.(暗示留下我可能为公司带来的益处) ...
- 初识Iaas,paas
Iaas(Infrastructure-as-a-service),直译为基础设备作为一种服务. Paas(Platform as a service),直译为平台作为一种服务. 暂且忘掉这两个单词, ...
- 设置ubuntu 默认不启动图形界面
设置ubuntu 默认不启动图形界面 一. 编辑文件/etc/X11/default-display-manager 如果值为/usr/sbin/gdm,则进入图形界面如果值为false,则进入控制台 ...