Universal Image Loader

来源:互联网 发布:访客网络什么意思 编辑:程序博客网 时间:2024/05/22 00:21

参考博文:http://blog.csdn.net/vipzjyno1/article/details/23206387

UIL的简单介绍

Univesial Image Loader是一个强大可扩展的、高度的可配置性的异步图片加载和缓存工具。
图片异步加载和缓存的开源工具有很多:譬如说Volley的ImageLoader,FaceBook的Fresco,但是Univesial Image Loader还因该是最普及的吧

UIL的使用

  1. 在Application中通过Builder建造者模式设置ImageLoaderConfiguration图片加载和缓存的配置信息,譬如说设置内存缓存、磁盘缓存的大小;线程池的大小;图片名称使用url的MD5加密命名啊这些设置。
ImageLoaderConfiguration config = new ImageLoaderConfiguration      .Builder(context)      .memoryCacheExtraOptions(480, 800) // max width, max height,即保存的每个缓存文件的最大长宽      .discCacheExtraOptions(480, 800, CompressFormat.JPEG, 75, null) // Can slow ImageLoader, use it carefully (Better don't use it)/设置缓存的详细信息,最好不要设置这个      .threadPoolSize(3)//线程池内加载的数量      .threadPriority(Thread.NORM_PRIORITY - 2)      .denyCacheImageMultipleSizesInMemory()      .memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024)) // You can pass your own memory cache implementation/你可以通过自己的内存缓存实现      .memoryCacheSize(2 * 1024 * 1024)        .discCacheSize(50 * 1024 * 1024)        .discCacheFileNameGenerator(new Md5FileNameGenerator())//将保存的时候的URI名称用MD5 加密      .tasksProcessingOrder(QueueProcessingType.LIFO)      .discCacheFileCount(100) //缓存的文件数量      .discCache(new UnlimitedDiscCache(cacheDir))//自定义缓存路径      .defaultDisplayImageOptions(DisplayImageOptions.createSimple())      .imageDownloader(new BaseImageDownloader(context, 5 * 1000, 30 * 1000)) // connectTimeout (5 s), readTimeout (30 s)超时时间      .writeDebugLogs() // Remove for release app      .build();//开始构建      // Initialize ImageLoader with configuration.  

3.通过Builder建造者模式设置DisplayImageOptions图片显示和缓存的配置信息,譬如说图片加载期间显示的图片、图片加载错误显示的图片,以及是否使用内存缓存和磁盘缓存。

ImageLoaderConfiguration config = new ImageLoaderConfiguration      .Builder(context)      .memoryCacheExtraOptions(480, 800) // max width, max height,即保存的每个缓存文件的最大长宽      .discCacheExtraOptions(480, 800, CompressFormat.JPEG, 75, null) // Can slow ImageLoader, use it carefully (Better don't use it)/设置缓存的详细信息,最好不要设置这个      .threadPoolSize(3)//线程池内加载的数量      .threadPriority(Thread.NORM_PRIORITY - 2)      .denyCacheImageMultipleSizesInMemory()      .memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024)) // You can pass your own memory cache implementation/你可以通过自己的内存缓存实现      .memoryCacheSize(2 * 1024 * 1024)        .discCacheSize(50 * 1024 * 1024)        .discCacheFileNameGenerator(new Md5FileNameGenerator())//将保存的时候的URI名称用MD5 加密      .tasksProcessingOrder(QueueProcessingType.LIFO)      .discCacheFileCount(100) //缓存的文件数量      .discCache(new UnlimitedDiscCache(cacheDir))//自定义缓存路径      .defaultDisplayImageOptions(DisplayImageOptions.createSimple())      .imageDownloader(new BaseImageDownloader(context, 5 * 1000, 30 * 1000)) // connectTimeout (5 s), readTimeout (30 s)超时时间      .writeDebugLogs() // Remove for release app      .build();//开始构建      // Initialize ImageLoader with configuration. 
  1. 最后根据ImageLoaderConfiguration的配置初始化ImageLoader单例。ImageLoader类根据DisplayImageOptions的设置要是调用displayImage(url, ImageView)方法加载图片并显示在特定的控件上,也可以在图片显示的时候设置监听或者是进度条:
imageLoader.displayImage(imageUrl, imageView, options, new ImageLoadingListener() {      @Override      public void onLoadingStarted() {         //开始加载的时候执行      }      @Override      public void onLoadingFailed(FailReason failReason) {               //加载失败的时候执行      }          @Override          public void onLoadingComplete(Bitmap loadedImage) {         //加载成功的时候执行      }          @Override          public void onLoadingCancelled() {         //加载取消的时候执行      },new ImageLoadingProgressListener() {              @Override        public void onProgressUpdate(String imageUri, View view, int current,int total) {           //在这里更新 ProgressBar的进度信息        }      });  

UIL图片下载方式

根据不同的网络状况(访问受限网络/慢速、正常)UIL分别有不同的图片加载策略(SlowNetworkDownloader、BaseImageLoader、NetworkDeniedDownloader)来应对这些策略,获取到图片对应的流对象之后,通过decode()方法将图片解析成Bitmap

UIL的主要类

这里写图片描述

UIL异步加载图片和缓存的一般流程

① UI:ListView中每个Item的Adapter根据图片url请求数据
② 内存缓存:先从内存缓存搜索,如果能找到url值对应的Bitmap,则返回数据并显示。
③ 磁盘存储:如果内存缓存中没有,在从操盘缓存中搜索,如果有这个url对应的bitmap的话,将图片解码并返回数据显示,同时将图片保存到内存缓存中。
④ 如果磁盘缓存中也没有该url对应的Bitmap的话就启动异步线程,从数据网络中下载图片数据并显示。同时将数据同时写入内存缓存和磁盘缓存。

图片缓存涉及到的知识点

( Java中的SoftReference,即对象的软引用。
如果一个对象具有软引用,内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。软引用可用来实现内存敏感的高速缓存。使用软引用能防止内存泄露,增强程序的健壮性。Map[String, SoftReference[Bitmap]])

* 内存缓存*
LruMemoryCache:LruMemoryCache类就是ImageLoader开源框架默认的内存缓存类,缓存的是bitmap的强引用,如果缓存的图片大小超过限定值,会使用Lru(最近最少使用算法)删除最近最少使用的Bitmap,ImageLoader也提供了其它可定制使用的内存缓存,譬如说:
2.使用强引用和弱引用相结合的缓存有
UsingFreqLimitedMemoryCache(如果缓存的图片大小超过限定值,先删除使用频率最小的bitmap)
LRULimitedMemoryCache(这个也是使用的lru算法,和LruMemoryCache不同的是,他缓存的是bitmap的弱引用)
FIFOLimitedMemoryCache(先进先出的缓存策略,当超过设定值,先删除最先加入缓存的bitmap)
LargestLimitedMemoryCache(当超过缓存限定值,先删除最大的bitmap对象)
LimitedAgeMemoryCache(当 bitmap加入缓存中的时间超过我们设定的值,将其删除)
3.只使用弱引用缓存
WeakMemoryCache(这个类缓存bitmap的总大小没有限制,唯一不足的地方就是不稳定,缓存的图片容易被回收掉)

LruMemoryCache实现原理介绍

  1. LruMemoryCache:一种使用强引用来保存有数量限制的Bitmap的cache(在空间有限的情况,保留最近使用过的Bitmap)。每次Bitmap被访问时,它就被移动到一个队列的头部。当Bitmap被添加到一个空间已满的cache时,在队列末尾的Bitmap会被挤出去并变成适合被GC回收的状态。
  2. 缓存采用的存储结构是:一个LinkedHashMap[String, Bitmap],LinkedHashMap使用双链表来保存数据
    1、LinkedHashMap中的get()方法不仅返回所匹配的值,并且在返回前还会将所匹配的key对应的entry对象调整在列表中的顺序,让它处于链表的尾部。(链表头被认为是最少使用的,链表尾被认为是最常使用的)
    2、LinkedHashMap中的put()方法在将值存入到链表之前,会进行缓存大小判定,如果缓存大小不足的话就删除聊表头部的对象,也就是最近最少使用的图片。

文件缓存

  1. UIL提供了几种常见的磁盘缓存策略,
    TotalSizeLimitedDiscCache(设定缓存bitmap的最大值,当超过这个值,删除最先加入到硬盘的图片)
    FileCountLimitedDiscCache(可以设定缓存图片的个数,当超过设定值,删除掉最先加入到硬盘的图片)
    LimitedAgeDiscCache(设定图片存储的的最长时间,当超过这个值,就删除该图片)
  2. 图片文件的命名:url的MD5加密命名 + url的hashcode命名

UIL线程池

  1. 总概述:ImageLoader要显示的图片可以从内存缓存、文件缓存或者是网络中获取。ImageLoader提供了三种线程池异步获取这些图片资源。
  2. 为什么要三种线程池而不用一种呢:因为App中最好还是按任务的类别来使用不同类型的线程池,而这里涉及到的线程有访问网络的线程,还有读写文件的线程,采用不同的线程池处理不同类型的任务能够有效的提高App性能
  3. ImageLoader采用的三种线程池
void submit(final LoadAndDisplayImageTask task) {    taskDistributor.execute(new Runnable() {        @Override        public void run() {           File image = configuration.diskCache.get(task.getLoadingUri());           boolean isImageCachedOnDisk = image != null && image.exists();           initExecutorsIfNeed();           if (isImageCachedOnDisk) {              taskExecutorForCachedImages.execute(task);           } else {               taskExecutor.execute(task);               }             }        });     }

1、taskDistributor,一个主线程池,任务分配器线程池,它首先访问文件,根据文件中是否有该的图片缓存,将图片加载的任务添加到到不同的线程池。
2、taskExecutorForCachedImages:如果文件中有该图片的缓存,则通过访问文件的线程池执行任务获取图片。
3、taskExecutor:如果文件中没有该图片的缓存,则通过访问网络的线程池执行任务获取图片
4. 三种线程池对应的配置:
这里写图片描述

即taskDistributor线程池采用的是缓存线城市、而taskExecutorForCachedImages和taskExecutor线程池采用的是固定大小的线城池

0 0
原创粉丝点击