图片加载机制的比较

来源:互联网 发布:mac电脑程序强制退出 编辑:程序博客网 时间:2024/06/08 03:53
包括:ImageLoader,Picasso,Glide,Fresco
1.ImageLoader介绍
ImageLoader的设计及优点
设计流程:

整个库分为 ImageLoaderEngine,Cache , ImageDownloader,ImageDecoder, BitmapDisplayer,BitmapProcessor 五大模块
    ImageLoader收到展示和加载图片的任务,并交给ImageLoaderEngine(创建任务,并进行任务调度)分配到具体的线程池去完成,任务通过 Cache( MemoryCache(内存缓存) 和 DiskCache(硬盘缓存) 两部分)及 ImageDownloader (从网络获取图片)获取图片,中间可能经过 BitmapProcessor(图片处理器 旋转、压缩、截取等) 和 ImageDecoder (图片解码)处理,最终转换为Bitmap 交给 BitmapDisplayer 在 ImageAware 中显示。
优点:
1.多线程下载图片,图片可以来源于网络,文件系统,项目文件夹assets中以及drawable中等
2.支持随意的配置ImageLoader,例如线程池,图片下载器,内存缓存策略,硬盘缓存策略,图片显示选项以及其他的一些配置
3.支持图片的内存缓存,文件系统缓存或者SD卡缓存
4.支持图片下载过程的监听
5.根据控件(ImageView)的大小对Bitmap进行裁剪,减少Bitmap占用过多的内存
6.较好的控制图片的加载过程,例如暂停图片加载,重新开始加载图片,一般使用在ListView,GridView中,滑动过程中暂停加载图片,停止滑动的时候去加载图片
7.提供在较慢的网络下对图片进行加载
8. 默认实现多种内存缓存算法 这几个图片缓存都可以配置缓存算法,不过 ImageLoader 默认实现了较多缓存算法,如 Size 最大先删除、使用最少先删除、最近最少使用、先进先删除、时间最长先删除等。
缺点:
不支持Gif动画;
使用步骤:
       1. 在Application子类中的onCreate方法中初始化ImageLoaderConfiguration 
缓存类型,缓存上限值,加载图片的线程池数量,是否使用disk缓存(存到sd卡里一般),加载图片失败时显示的图片,默认图片,图片的色彩样式
1
2
3
4
5
6
7
8
9
10
ImageLoaderConfiguration config = newImageLoaderConfiguration.Builder(context)//
  .threadPriority(Thread.NORM_PRIORITY - 2)//
  .denyCacheImageMultipleSizesInMemory()//
  .diskCacheFileNameGenerator(newMd5FileNameGenerator())//
  .diskCacheSize(50* 1024* 1024) // 50 Mb
  .memoryCache(newLruMemoryCache(4* 1024* 1024)).tasksProcessingOrder(QueueProcessingType.LIFO)//
  .writeDebugLogs() // Remove for release app
  .build();
 // Initialize ImageLoader with configuration.
 ImageLoader.getInstance().init(config);
       2. 在具体的地方直接 
?
1
2
3
4
5
6
7
8
9
10
11
//图片加载
 // ImageLoader.getInstance().displayImage(data.url, holder.ivIcon);
    DisplayImageOptions option = newDisplayImageOptions.Builder()
        .resetViewBeforeLoading(true)
        .cacheOnDisk(true)
        .imageScaleType(ImageScaleType.EXACTLY)
        .bitmapConfig(Bitmap.Config.RGB_565)
        .considerExifParams(true)
        .displayer(newFadeInBitmapDisplayer(300))
        .build();
    ImageLoader.getInstance().displayImage(data.url, holder.ivIcon, option);
     3. 加载各种格式图片
?
1
2
3
4
5
String imageUri = "http://site.com/image.png"; // 网络图片
String imageUri = "file:///mnt/sdcard/image.png"; //SD卡图片
String imageUri = "content://media/external/audio/albumart/13"; // 媒体文件夹
String imageUri = "assets://image.png"; // assets
String imageUri = "drawable://"+ R.drawable.image; // drawable文件
     4. 提供了丰富的缓存策略 
         内存缓存,现在我们来看Universal-Image-Loader有哪些内存缓存策略
        1. 只使用的是强引用缓存
            LruMemoryCache(这个类就是这个开源框架默认的内存缓存类,缓存的是bitmap的强引用,下面我会从源码上面分析这个类)
        2.使用强引用和弱引用相结合的缓存有
           UsingFreqLimitedMemoryCache(如果缓存的图片总量超过限定值,先删除使用频率最小的bitmap)
           LRULimitedMemoryCache(这个也是使用的lru算法,和LruMemoryCache不同的是,他缓存的是bitmap的弱引用)
           FIFOLimitedMemoryCache(先进先出的缓存策略,当超过设定值,先删除最先加入缓存的bitmap)
           LargestLimitedMemoryCache(当超过缓存限定值,先删除最大的bitmap对象)
           LimitedAgeMemoryCache(当 bitmap加入缓存中的时间超过我们设定的值,将其删除)
        3.只使用弱引用缓存
           WeakMemoryCache(这个类缓存bitmap的总大小没有限制,唯一不足的地方就是不稳定,缓存的图片容易被回收硬盘缓存)
           FileCountLimitedDiscCache(可以设定缓存图片的个数,当超过设定值,删除掉最先加入到硬盘的文件)
           LimitedAgeDiscCache(设定文件存活的最长时间,当超过这个值,就删除该文件)
           TotalSizeLimitedDiscCache(设定缓存bitmap的最大值,当超过这个值,删除最先加入到硬盘的文件)
           UnlimitedDiscCache(这个缓存类没有任何的限制)
ImageLoader的配置:
ImageLoaderConfiguration、ImageLoader、DisplayImageOptions
ImageLoaderConfiguration是针对图片缓存的全局配置,主要有线程类、缓存大小、磁盘大小、图片下载与解析、日志方面的配置。
ImageLoader是具体下载图片,缓存图片,显示图片的具体执行类,它有两个具体的方法displayImage(...)、loadImage(...),但是其实最终他们的实现都是displayImage(...)。
DisplayImageOptions用于指导每一个Imageloader根据网络图片的状态(空白、下载错误、正在下载)显示对应的图片,是否将缓存加载到磁盘上,下载完后对图片进行怎么样的处理。
从三者的协作关系上看,他们有点像厨房规定、厨师、客户个人口味之间的关系。ImageLoaderConfiguration就像是厨房里面的规定,每一个厨师要怎么着装,要怎么保持厨房的干净,这是针对每一个厨师都适用的规定,而且不允许个性化改变。ImageLoader就像是具体做菜的厨师,负责具体菜谱的制作。DisplayImageOptions就像每个客户的偏好,根据客户是重口味还是清淡,每一个imageLoader根据DisplayImageOptions的要求具体执行
二、Picasso介绍
   picasso是Square公司开源的一个Android图形缓存库,可以实现图片下载和缓存功能
    Picasso不仅实现了图片异步加载的功能,还解决了android中加载图片时需要解决的一些常见问题:
   1.在adapter中需要取消已经不在视野范围的ImageView图片资源的加载,否则会导致图片错位,Picasso已经解决了这个问题。
   2.使用复杂的图片压缩转换来尽可能的减少内存消耗
   3.自带内存和硬盘二级缓存功能
Picasso设计与流程设计

 Picasso 收到加载及显示图片的任务,创建 Request 并将它交给 Dispatcher,Dispatcher 分发任务到具体 RequestHandler,任务通过 MemoryCache 及 Handler(数据获取接口) 获取图片,图片获取成功后通过 PicassoDrawable 显示到 Target 中。
注:Dispatcher 负责分发和处理 Action,包括提交、暂停、继续、取消、网络状态变化、重试等等。
优点
1.自带统计监控功能。支持图片缓存使用的监控,包括缓存命中率、已使用内存大小、节省的流量等。
2.支持优先级处理。每次任务调度前会选择优先级高的任务
3.支持延迟到图片尺寸计算完成加载
4.支持飞行模式、并发线程数根据网络类型而变。 手机切换到飞行模式或网络类型变换时会自动调整线程池最大并发数,比如 wifi 最大并发为 4,4g 为 3,3g 为 2。  这里 Picasso 根据网络类型来决定最大并发数,而不是 CPU 核数。
5.“无”本地缓存。无”本地缓存,不是说没有本地缓存,而是 Picasso 自己没有实现,交给了 Square 的另外一个网络库 okhttp 去实现,这样的好处是可以通过请求 Response Header 中的 Cache-Control 及 Expired 控制图片的过期时间。
      使用步骤:
        1. 导入Picasso的jar包,添加依赖
        2. 加载图片
?
1
2
3
4
5
//图片加载
  Picasso.with(mContext)    //创建Picasso
      .load(data.url)    //传入路径
      .fade(300)      //淡化效果时长
      .into(holder.ivIcon); //图片加载到那个位置
 
 
 
 三、Glide简介
   Glide是一个高效、开源、 Android设备上的媒体管理框架,Glide具有获取、解码和展示视频剧照、图片、动画等功能,它还有灵活的API,这些API使开发者能够将Glide应用在几乎任何网络协议栈里。创建Glide的主要目的有两个,一个是实现平滑的图片列表滚动效果(滚动流畅),另一个是支持远程图片的获取、大小调整和展示
Glide可以说是 Picasso 的升级版, 有 Picasso 的优点, 并且支持 GIF 图片加载显示, 图片缓存也会自动缩放, 默认使用 RGB_565 格式缓存图片, 是 Picasso 缓存体积的一半。整个库分为 RequestManager(请求管理器),Engine(数据获取引擎)、 Fetcher(数据获取器)、MemoryCache(内存缓存)、DiskLRUCache、Transformation(图片处理)、Encoder(本地缓存存储)、Registry(图片类型及解析器配置)、Target(目标) 等模块。

Glide设计与流程

   简单的讲就是 Glide 收到加载及显示资源的任务,创建 Request 并将它交给RequestManager(任务管理器),Request 启动 Engine(数据获取引擎) 去数据源获取资源(通过 Fetcher(数据获取器) ),获取到后 Transformation(图片处理) 处理后交给 Target(目标),Glide 依赖于 DiskLRUCache、GifDecoder 等开源库去完成本地缓存和 Gif 图片解码工作。
Glide 优点
(1) 图片缓存->媒体缓存
Glide 不仅是一个图片缓存,它支持 Gif、WebP、缩略图。甚至是 Video,所以更该当做一个媒体缓存。
(2) 支持优先级处理
(3) 与 Activity/Fragment 生命周期一致,支持 trimMemory
Glide 对每个 context 都保持一个 RequestManager,通过 FragmentTransaction 保持与 Activity/Fragment 生命周期一致,并且有对应的 trimMemory 接口实现可供调用。
(4) 支持 okhttp、Volley
Glide 默认通过 UrlConnection 获取数据,可以配合 okhttp 或是 Volley 使用。实际 ImageLoader、Picasso 也都支持 okhttp、Volley。
(5) 内存友好
① Glide 的内存缓存有个 active 的设计
从内存缓存中取数据时,不像一般的实现用 get,而是用 remove,再将这个缓存数据放到一个 value 为软引用的 activeResources map 中,并计数引用数,在图片加载完成后进行判断,如果引用计数为空则回收掉。
② 内存缓存更小图片
Glide 以 url、viewwidth、viewheight、屏幕的分辨率等做为联合 key,将处理后的图片缓存在内存缓存中,而不是原始图片以节省大小
③ 与 Activity/Fragment 生命周期一致,支持 trimMemory
④ 图片默认使用默认 RGB565 而不是 ARGB8888
虽然清晰度差些,但图片更小,也可配置到 ARGB_8888。
 >>特点
  • GIF动画的解码:通过调用Glide.with(context).load(“图片路径“)方法,GIF动画图片可以自动显示为动画效果。如果想有更多的控制,还可以使用Glide.with(context).load(“图片路径“).asBitmap()方法加载静态图片,使用Glide.with(context).load(“图片路径“).asGif()方法加载动画图片
  • 本地视频剧照的解码:通过调用Glide.with(context).load(“图片路径“)方法,Glide能够支持Android设备中的所有视频剧照的加载和展示
  • 缩略图的支持:为了减少在同一个view组件里同时加载多张图片的时间,可以调用Glide.with(context).load(“图片路径“).thumbnail(“缩略比例“).into(“view组件“)方法加载一个缩略图,还可以控制thumbnail()中的参数的大小,以控制显示不同比例大小的缩略图
  • Activity生命周期的集成:当Activity暂停和重启时,Glide能够做到智能的暂停和重新开始请求,并且当Android设备的连接状态变化时,所有失败的请求能够自动重新请求
  • 转码的支持:Glide的toBytes() 和transcode() 两个方法可以用来获取、解码和变换背景图片,并且transcode() 方法还能够改变图片的样式
  • 动画的支持:新增支持图片的淡入淡出动画效果(调用crossFade()方法)和查看动画的属性的功能
  • OkHttp和Volley的支持:默认选择HttpUrlConnection作为网络协议栈,还可以选择OkHttp和Volley作为网络协议栈
  • 其他功能:如在图片加载过程中,使用Drawables对象作为占位符、图片请求的优化、图片的宽度和高度可重新设定、缩略图和原图的缓存等功能
  • Glide默认的Bitmap格式是RGB_565,比    Picasso默认的ARGB_8888格式的内存开销要小一半;Picasso缓存的是全尺寸的(只缓存一种),而Glide缓存的是跟ImageView尺寸相同的(即56*56和128*128是两个缓存)
    使用步骤
    1. 导入Glide的jar包,添加依赖
    2. 加载图片       
1
2
3
Glide.with(mContext)   //创建Glide
   .load(data.url)   //传入路径
   .into(holder.ivIcon);//图片加载到那个位置
4.Fresco,
Fresco 是 Facebook 推出的开源图片缓存工具,主要特点包括:两个内存缓存加上 Native 缓存构成了三级缓存,支持流式,可以类似网页上模糊渐进式显示图片,对多帧动画图片支持更好,如 Gif、WebP。它的优点是其他几个框架没有的, 或者说是其他几个框架的短板。
      优点:
         1. 图片存储在安卓系统的匿名共享内存, 而不是虚拟机的堆内存中, 图片的中间缓冲数据也存放在本地堆内存, 所以, 应用程序有更多的内存使用, 不会因为图片加载而导致oom, 同时也减少垃圾回收器频繁调用回收 Bitmap 导致的界面卡顿, 性能更高。
         2. 渐进式加载 JPEG 图片, 支持图片从模糊到清晰加载。
         3. 图片可以以任意的中心点显示在 ImageView, 而不仅仅是图片的中心。
         4. JPEG 图片改变大小也是在 native 进行的, 不是在虚拟机的堆内存, 同样减少 OOM。
         5. 很好的支持 GIF 图片的显示。
6.在5.0以下系统,Fresco将图片放到一个特别的内存区域(Ashmem区)。当然,在图片不显示的时候,占用的内存会自动被释放。这会使得APP更加流畅,减少因图片内存占用而引发的OOM
    缺点:
         1. 框架较大, 影响 Apk 体积
         2. 使用较繁琐
    使用步骤:
      1. 引入 Fresco,包括两种方式,在线和离线。
          在线引入依赖脚本形式,在dependencies中添加依赖,
?
1
compile 'com.facebook.fresco:fresco:0.9.0'
          引入离线引入,需要导入的arr包较多,包括:
?
1
2
3
4
5
compile(name: 'drawee-0.9.0', ext: 'aar')
compile(name: 'fbcore-0.9.0', ext: 'aar')
compile(name: 'imagepipeline-0.9.0', ext: 'aar')
compile(name: 'imagepipeline-base-0.9.0', ext: 'aar')
compile files('libs/bolts-android-1.1.4.jar')
          上面提到的aar其实就是lib module压缩包的形式,包括.class和相关的资源文件,平常使用的jar仅仅包括.class文件。使用aar包时,还需要来到project `build.gradle`里面, 在allprojects方法体加入  
?
1
2
3
4
5
6
7
8
9
allprojects {
    repositories {
       jcenter()
        //add begin
        flatDir {
          dirs 'libs'
        }
       //add end
     }
   2. 需要在程序入口方法里面进行初始化。在oncreate方法中添加初始化语句。       
1
Fresco.initialize(context);<br>
   3. 在布局文件中,需要使用图片展示地方,使用它定义的控件
1
2
3
4
5
6
7
8
<com.facebook.drawee.view.SimpleDraweeView
     android:id="@+id/iv_img"
     android:layout_width="150dp"
     android:layout_height="150dp"
     android:src="@mipmap/ic_launcher"
     fresco:fadeDuration="300"
     fresco:roundingBorderColor="#ccc"
     fresco:roundingBorderWidth="2dp"/>
   4.设置静态图片,在代码中具体写如下代码 
?
1
2
3
4
// 图片加载
     Uri uri = Uri.parse(data.url);
 holder.ivIcon.setImageURI(uri);
   5. 设置gif图片,在代码中具体写如下代码
?
1
2
3
4
DraweeController gifController = Fresco.newDraweeControllerBuilder().setUri(uri)
        .setAutoPlayAnimations(true).build();
    holder.ivIcon.setController(gifController);

第一、Gif的支持
Fresco  支持
Glide     支持
Picasso 不支持
ImageLoader 不支持

第二、内存与性能

1、Fresco:
FaceBook出品,
优点:(1)支持图像渐进式呈现
      (2)大公司出品,后期维护有保障
缺点:(1)框架体积较大3M左右会增大apk的大小
          (2)操作方式不是特别简单,有一定学习成本
特点:有两级内存一级文件的缓存机制,并且有自己特别的内存区域来处理缓存,避免oom
2、Glide:
谷歌员工出品,Google推荐的图片加载库,专注于流畅的滚动
优点:(1)加载速度极快
   (2)框架体积小  四五百KB
缺点:(1)因为机制的选择不同,速度快了,但是图片质量低了 RGB565
特点:根据ImageView大小来进行缓存,也就是说一张图片可能根据展示情况来缓存不同尺寸的几份
3、Picasso:
Square出品,
优点:(1)图片质量高
缺点:(1)加载速度一般
特点:只缓存一个全尺寸的图片,根据需求的大小在压缩转换
4、Universal-Imager-Loader
sergey Tarasevice出品,
优点:(1)丰富的配置选项
缺点:(1)最近一次维护在15年底,后期有不维护的趋势,可能被当前图片框架替代
特点:三级缓存的策略

原创粉丝点击