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

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

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

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

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

  1. public class ImageLoadUtil {
  2. private static ImageLoadUtil imageLoadUtil = null;
  3. private ImageLoaderConfiguration config = null;
  4. private DisplayImageOptions options = null;
  5. private ImageLoadUtil(Context context){
  6. options = new DisplayImageOptions.Builder()
  7. //.showImageOnLoading(R.drawable.ic_launcher) //设置图片在下载期间显示的图片
  8. //.showImageForEmptyUri(R.drawable.ic_launcher)//设置图片Uri为空或是错误的时候显示的图片
  9. //.showImageOnFail(R.drawable.ic_launcher) //设置图片加载/解码过程中错误时候显示的图片
  10. .cacheInMemory(true)//设置下载的图片是否缓存在内存中
  11. .cacheOnDisc(true)//设置下载的图片是否缓存在SD卡中
  12. .considerExifParams(true) //是否考虑JPEG图像EXIF参数(旋转,翻转)
  13. .imageScaleType(ImageScaleType.EXACTLY_STRETCHED)//设置图片以如何的编码方式显示
  14. .bitmapConfig(Bitmap.Config.RGB_565)//设置图片的解码类型//
  15. //.delayBeforeLoading(int delayInMillis)//int delayInMillis为你设置的下载前的延迟时间
  16. //设置图片加入缓存前,对bitmap进行设置
  17. //.preProcessor(BitmapProcessor preProcessor)
  18. .resetViewBeforeLoading(true)//设置图片在下载前是否重置,复位
  19. .displayer(new RoundedBitmapDisplayer(20))//是否设置为圆角,弧度为多少
  20. .displayer(new FadeInBitmapDisplayer(100))//是否图片加载好后渐入的动画时间
  21. .build();//构建完成
  22.  
  23. config = new ImageLoaderConfiguration.Builder(
  24. context).threadPriority(Thread.NORM_PRIORITY - 2)// 加载图片的线程数
  25. .denyCacheImageMultipleSizesInMemory() // 解码图像的大尺寸将在内存中缓存先前解码图像的小尺寸。
  26. .discCacheFileNameGenerator(new Md5FileNameGenerator())// 设置磁盘缓存文件名称
  27. .tasksProcessingOrder(QueueProcessingType.LIFO)// 设置加载显示图片队列进程
  28. .writeDebugLogs() // Remove for release app
  29. .discCache(new UnlimitedDiscCache(new File(FileCacheUtil.getPicCacheDir()))) // 文件缓存目录
  30. .defaultDisplayImageOptions(options)// 创建配置过得DisplayImageOption对象
  31. .build();
  32. /*config = new ImageLoaderConfiguration.Builder(context)
  33. .threadPriority(Thread.NORM_PRIORITY - 2)
  34. .denyCacheImageMultipleSizesInMemory()
  35. .diskCacheFileNameGenerator(new Md5FileNameGenerator())
  36. .tasksProcessingOrder(QueueProcessingType.LIFO)
  37. .writeDebugLogs()
  38. .build();*/
  39. ImageLoader.getInstance().init(config);
  40. }
  41.  
  42. public static ImageLoadUtil init(Context context){
  43. if (imageLoadUtil == null) {
  44. imageLoadUtil = new ImageLoadUtil(context);
  45. }
  46. return imageLoadUtil;
  47. }
  48. }

首先分析:ImageLoaderConfiguration

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

  1. //设置内存缓存的选项,用于将图片将图片解析成最大指定宽高的大小的图片进行缓存(缓存在内存中的图片宽高)。
  2. memoryCacheExtraOptions(int maxImageWidthForMemoryCache, int maxImageHeightForMemoryCache)
  3.  
  4. //设置磁盘缓存的选项,maxImageWidthForDiskCache()和maxImageHeightForDiskCache()缓存在硬盘里面图片最大尺寸。
  5.  
  6. diskCacheExtraOptions(int maxImageWidthForDiskCache, int maxImageHeightForDiskCache, BitmapProcessor processorForDiskCache)
  7.  
  8. //设置自定义加载和显示任务的线程池
  9. taskExecutor(Executor executor)
  10.  
  11. //设置自定义显示任务的线程池
  12. taskExecutorForCachedImages(Executor executorForCachedImages)
  13.  
  14. //设置图片显示任务的线程池大小
  15. threadPoolSize(int threadPoolSize)
  16.  
  17. //设置线程的优先级
  18. threadPriority(int threadPriority)
  19.  
  20. //设置拒绝缓存一张图片的多个尺寸
  21. denyCacheImageMultipleSizesInMemory()
  22.  
  23. //设置加载和显示图片任务队列的类型
  24. tasksProcessingOrder(QueueProcessingType tasksProcessingType)
  25.  
  26. //设置最大内存缓存字节数
  27. memoryCacheSize(int memoryCacheSize)
  28.  
  29. //设置最大内存缓存所占app可用内存的百分比
  30. memoryCacheSizePercentage(int availableMemoryPercent)
  31.  
  32. //设置内存缓存算法
  33. memoryCache(MemoryCache memoryCache)
  34.  
  35. //设置最大磁盘缓存字节数
  36. diskCacheSize(int maxCacheSize)
  37.  
  38. //设置在磁盘缓存文件夹下最多文件数
  39. diskCacheFileCount(int maxFileCount)
  40.  
  41. //设置磁盘缓存文件生成的命名规则
  42. diskCacheFileNameGenerator(FileNameGenerator fileNameGenerator)
  43.  
  44. //设置磁盘缓存
  45. diskCache(DiskCache diskCache)
  46.  
  47. //设置下载图片的工具
  48. imageDownloader(ImageDownloader imageDownloader)
  49.  
  50. //设置decode出bitmap的工具
  51. imageDecoder(ImageDecoder imageDecoder)
  52.  
  53. //设置默认的DisplayImageOptions
  54. defaultDisplayImageOptions(DisplayImageOptions defaultDisplayImageOptions)
  55.  
  56. //log信息
  57. writeDebugLogs()
  58.  
  59. public ImageLoaderConfiguration build() {
  60. initEmptyFieldsWithDefaultValues();
  61. return new ImageLoaderConfiguration(this);
  62. }
  63.  
  64. 在分析DisplayImageOptions(图片加载过程中各种情况的处理):
  65.  
  66. //设置图片加载过程中显示的图片
  67. showImageOnLoading(int imageRes)
  68.  
  69. //设置空URI显示的图片
  70. showImageForEmptyUri(int imageRes)
  71.  
  72. //设置发生错误显示的图片
  73. showImageOnFail(int imageRes)
  74.  
  75. //设置图片加载前是否重置
  76. resetViewBeforeLoading(boolean resetViewBeforeLoading)
  77.  
  78. //设置是否将图片缓存在内存里
  79. cacheInMemory(boolean cacheInMemory)
  80.  
  81. //设置是否将图片缓存在磁盘上
  82. cacheOnDisk(boolean cacheOnDisk)
  83.  
  84. //设置图片缩放的类型
  85. imageScaleType(ImageScaleType imageScaleType)
  86.  
  87. //设置Bitmap.Config
  88. bitmapConfig(Bitmap.Config bitmapConfig)
  89.  
  90. //设置图片解码的选项
  91. decodingOptions(Options decodingOptions)
  92.  
  93. //设置加载任务前的延迟
  94. delayBeforeLoading(int delayInMillis)
  95.  
  96. //设置下载时额外的对象
  97. extraForDownloader(Object extra)
  98.  
  99. //设置是否考虑EXIF信息
  100. considerExifParams(boolean considerExifParams)
  101.  
  102. //设置内存缓存bitmap对象前的处理
  103. preProcessor(BitmapProcessor preProcessor)
  104.  
  105. //设置内存缓存bitmap对象后的处理
  106. postProcessor(BitmapProcessor postProcessor)
  107.  
  108. //设置图片的显示方式
  109. displayer(BitmapDisplayer displayer)
  110.  
  111. //true是直接调用LoadAndDisplayImageTask对象的run方法,false是放到线程池里面执行,默认false
  112. syncLoading(boolean isSyncLoading)
  113.  
  114. //设置显示图片和触发ImageLoadingListener事件的自定义Handler对象
  115. handler(Handler handler)

ImageLoader使用的是单利模式:

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

  1. public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options,
  2. ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {
  3. //检查UIL的配置是否被初始化
  4. checkConfiguration();
  5. if (imageAware == null) {
  6. throw new IllegalArgumentException(ERROR_WRONG_ARGUMENTS);
  7. }
  8. if (listener == null) {
  9. listener = emptyListener;
  10. }
  11. if (options == null) {
  12. options = configuration.defaultDisplayImageOptions;
  13. }
  14.  
  15. if (TextUtils.isEmpty(uri)) {
  16. engine.cancelDisplayTaskFor(imageAware);
  17. listener.onLoadingStarted(uri, imageAware.getWrappedView());
  18. //没有图片时,显示displayImage传过来的图片不存在情况下的图片
  19. if (options.shouldShowImageForEmptyUri()) {
  20. imageAware.setImageDrawable(options.getImageForEmptyUri(configuration.resources));
  21. } else {
  22. imageAware.setImageDrawable(null);
  23. }
  24. listener.onLoadingComplete(uri, imageAware.getWrappedView(), null);
  25. return;
  26. }

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

  1. ImageSize targetSize = ImageSizeUtils.defineTargetSizeForView(imageAware, configuration.getMaxImageSize());
  2. //内存缓存的名称
  3. String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize);
  4. engine.prepareDisplayTaskFor(imageAware, memoryCacheKey);
  5.  
  6. listener.onLoadingStarted(uri, imageAware.getWrappedView());
  7. //Bitmap是否缓存在内存?
  8. Bitmap bmp = configuration.memoryCache.get(memoryCacheKey);
  9. if (bmp != null && !bmp.isRecycled()) {
  10. L.d(LOG_LOAD_IMAGE_FROM_MEMORY_CACHE, memoryCacheKey);
  11.  
  12. if (options.shouldPostProcess()) {
  13. ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey,
  14. options, listener, progressListener, engine.getLockForUri(uri));
  15. //处理并显示图片
  16. ProcessAndDisplayImageTask displayTask = new ProcessAndDisplayImageTask(engine, bmp, imageLoadingInfo,
  17. defineHandler(options));
  18. if (options.isSyncLoading()) {
  19. displayTask.run();
  20. } else {
  21. engine.submit(displayTask);
  22. }
  23. } else {
  24. //显示图片
  25. options.getDisplayer().display(bmp, imageAware, LoadedFrom.MEMORY_CACHE);
  26. listener.onLoadingComplete(uri, imageAware.getWrappedView(), bmp);
  27. }
  28. } else {
  29. //根据状态显示正在加载还是加载前的情况
  30. if (options.shouldShowImageOnLoading()) {
  31. imageAware.setImageDrawable(options.getImageOnLoading(configuration.resources));
  32. } else if (options.isResetViewBeforeLoading()) {
  33. imageAware.setImageDrawable(null);
  34. }
  35.  
  36. ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey,
  37. options, listener, progressListener, engine.getLockForUri(uri));
  38. //启动一个线程,加载并显示图片
  39. LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(engine, imageLoadingInfo,
  40. defineHandler(options));
  41. if (options.isSyncLoading()) {
  42. displayTask.run();
  43. } else {
  44. engine.submit(displayTask);
  45. }
  46. }
  47. }

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

  1. private Bitmap tryLoadBitmap() throws TaskCancelledException {
  2. Bitmap bitmap = null;
  3. try {
  4. //尝试从磁盘缓存中读取Bitmap
  5. File imageFile = configuration.diskCache.get(uri);
  6. //如果内存中有该图片,加载
  7. if (imageFile != null && imageFile.exists()) {
  8. L.d(LOG_LOAD_IMAGE_FROM_DISK_CACHE, memoryCacheKey);
  9. loadedFrom = LoadedFrom.DISC_CACHE;
  10.  
  11. checkTaskNotActual();
  12. bitmap = decodeImage(Scheme.FILE.wrap(imageFile.getAbsolutePath()));
  13. }
  14. //没有缓存在磁盘,从网络中下载图片
  15. if (bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
  16. L.d(LOG_LOAD_IMAGE_FROM_NETWORK, memoryCacheKey);
  17. loadedFrom = LoadedFrom.NETWORK;
  18.  
  19. String imageUriForDecoding = uri;
  20. //将网络里面的图片缓存到SD卡里面
  21. if (options.isCacheOnDisk() && tryCacheImageOnDisk()) {
  22. imageFile = configuration.diskCache.get(uri);
  23. if (imageFile != null) {
  24. imageUriForDecoding = Scheme.FILE.wrap(imageFile.getAbsolutePath());
  25. }
  26. }
  27.  
  28. checkTaskNotActual();
  29. bitmap = decodeImage(imageUriForDecoding);
  30.  
  31. if (bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
  32. fireFailEvent(FailType.DECODING_ERROR, null);
  33. }
  34. }
  35. } catch (IllegalStateException e) {
  36. fireFailEvent(FailType.NETWORK_DENIED, null);
  37. } catch (TaskCancelledException e) {
  38. throw e;
  39. } catch (IOException e) {
  40. L.e(e);
  41. fireFailEvent(FailType.IO_ERROR, e);
  42. } catch (OutOfMemoryError e) {
  43. L.e(e);
  44. fireFailEvent(FailType.OUT_OF_MEMORY, e);
  45. } catch (Throwable e) {
  46. L.e(e);
  47. fireFailEvent(FailType.UNKNOWN, e);
  48. }
  49. return bitmap;
  50. }
  51.  
  52. tryCacheImageOnDisk()里面是:
  53.  
  54. loaded = downloadImage();
  55.  
  56. private boolean downloadImage() throws IOException {
  57. //获取图片输入流
  58. InputStream is = getDownloader().getStream(uri, options.getExtraForDownloader());
  59. if (is == null) {
  60. L.e(ERROR_NO_IMAGE_STREAM, memoryCacheKey);
  61. return false;
  62. } else {
  63. try {
  64. //不为null,进行SD卡保存
  65. return configuration.diskCache.save(uri, is, this);
  66. } finally {
  67. IoUtils.closeSilently(is);
  68. }
  69. }
  70. }

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

  1. public boolean save(String imageUri, InputStream imageStream, IoUtils.CopyListener listener) throws IOException {
  2. File imageFile = getFile(imageUri);
  3. //tmp的临时文件
  4. File tmpFile = new File(imageFile.getAbsolutePath() + TEMP_IMAGE_POSTFIX);
  5. boolean loaded = false;
  6. try {
  7. OutputStream os = new BufferedOutputStream(new FileOutputStream(tmpFile), bufferSize);
  8. try {
  9. loaded = IoUtils.copyStream(imageStream, os, listener, bufferSize);
  10. } finally {
  11. //将临时文件tmpFile重命名回imageFile,并将tmpFile删除掉
  12. IoUtils.closeSilently(os);
  13. }
  14. } finally {
  15. if (loaded && !tmpFile.renameTo(imageFile)) {
  16. loaded = false;
  17. }
  18. if (!loaded) {
  19. tmpFile.delete();
  20. }
  21. }
  22. //true save成功
  23. //false save失败
  24. return loaded;
  25. }

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. 关于oracle数据库(4)数据类型

    数据类型 字符数据类型char:固定长度字符串,最大可以存放2000字节 字符串varchar2:可变长度字符串,最大可以存放2GB数值类型数据 数字number:可以存放整数.浮点数.实数 numb ...

  2. oracle行转列函数

  3. 【2】docker 与UFW

    ufw是一个主机端的iptables类防火墙配置工具. 1.查看ufw的状态:ufw status 2.如果使用UFW,需要对其进行修改才能让DOCKER工作.docker使用一个网桥来管理容器中的网 ...

  4. mysql 1053错误,无法启动的解决方法

    mysql 1053错误,无法启动的解决方法 windows2003服务器中,服务器重启后Mysql却没有启动,手动启动服务时提示1053错误. 尝试了以下方法,终于解决. 1.在DOS命令行使用 第 ...

  5. nfs服务器的建立

    NFS服务器的配置 一.NFS服务器端的配置,即共享发布者 (一)需启动的服务和需安装的软件 1.NFS服务器必须启动两个daemons服务:rpc.nfsd和rpc.mountd   rpc.nfs ...

  6. ADT(abstract data types)抽象数据类型

    1.What is it? An abstract data type is a set of objects together with a set of operations. 抽象数据类型是带有 ...

  7. while;do while;switch;break;continue

    1.while: 格式:while(判断条件) {    满足条件要执行的语句    } while语句与for语句对比(小九九) 1.1  for <script>for (var i= ...

  8. .NET面试题目二

    1.对你来说工作中最重要的是什么? 答:团队目标的实现.(这是所有公司希望员工拥有的素质) 2.为什么愿意为本公司工作? 答:因为我认为我可以与贵公司取得共同的发展.(暗示留下我可能为公司带来的益处) ...

  9. 初识Iaas,paas

    Iaas(Infrastructure-as-a-service),直译为基础设备作为一种服务. Paas(Platform as a service),直译为平台作为一种服务. 暂且忘掉这两个单词, ...

  10. 设置ubuntu 默认不启动图形界面

    设置ubuntu 默认不启动图形界面 一. 编辑文件/etc/X11/default-display-manager 如果值为/usr/sbin/gdm,则进入图形界面如果值为false,则进入控制台 ...