Fresco 图片加载

关于Fresco

fresco官网: http://www.fresco-cn.org/
fresco先包括两个大板块:Image Pipeline和Drawees.
Fresco 是一个强大的图片加载组件。 Fresco 中设计有一个叫做*image pipeline*的模块。它负责从网络,从本地文件系统,本地资源加载图片。为了最大限度节省空间和CPU时间,它含有3级缓存设计(2级内存,1级文件)。 Fresco 中设计有一个叫做*Drawees*模块,方便地显示loading图,当图片不再显示在屏幕上时,及时地释放内存和空间占用。 Fresco 支持 Android2.3(API level 9) 及其以上系统。

环境搭建
compile 'com.facebook.fresco:fresco:1.3.0'// 支持webpcompile 'com.facebook.fresco:webpsupport:1.3.0'// gif加载使用compile 'com.facebook.fresco:animated-gif:1.3.0'// WebP(静态图+动图)加载使用compile 'com.facebook.fresco:animated-webp:1.3.0'


基本概念
我们先简单了解下fresco中的重要类
DraweeView:继承自View,一般情况下我们使用SimpleDraweeView类进行图片加载。关于其自定义属性稍后我们介绍
DraweeHierarchy:渲染图片内容的类,我们可以通过它在java代码里设置DraweeView的属性
DraweeController:负责框架底层的图片加载的类
Image Pipeline:(图形管道)完成图片的获取。不管是通过网络、本地文件、content provider还是本地资源,它都把图片压缩并缓存到磁盘,并且把内存作为第二缓存存储着解码后的图片


特性介绍
1. Image Pipeline
Fresco 中设计有一个叫做 Image Pipeline 的模块。它负责从网络,从本地文件系统,本地资源加载图片。为了最大限度节省空间和CPU时间,它含有3级缓存设计(2级内存,1级磁盘)。
2. Drawees
Fresco 中设计有一个叫做 Drawees 模块,它会在图片加载完成前显示占位图,加载成功后自动替换为目标图片。当图片不再显示在屏幕上时,它会及时地释放内存和空间占用。
3. 内存管理
解压后的图片,即Android中的Bitmap,占用大量的内存。大的内存占用势必引发更加频繁的GC。在5.0以下,GC将会显著地引发界面卡顿。
在5.0以下系统,Fresco将图片放到一个特别的内存区域。当然,在图片不显示的时候,占用的内存会自动被释放。这会使得APP更加流畅,减少因图片内存占用而引发的OOM。
4. 图片加载
Fresco的Image Pipeline允许你用很多种方式来自定义图片加载过程,比如:
  • 为同一个图片指定不同的远程路径,或者使用已经存在本地缓存中的图片
  • 先显示一个低清晰度的图片,等高清图下载完之后再显示高清图
  • 加载完成回调通知
  • 对于本地图,如有EXIF缩略图,在大图加载完成之前,可先显示缩略图
  • 缩放或者旋转图片
  • 对已下载的图片再次处理
5. 图片绘制
Fresco 的 Drawees 设计,带来一些有用的特性:
  • 自定义居中焦点
  • 圆角图,当然圆圈也行
  • 下载失败之后,点击重现下载
  • 自定义占位图,自定义overlay, 或者进度条
  • 指定用户按压时的overlay
6. 图片的渐进式呈现
渐进式的JPEG图片格式已经流行数年了,渐进式图片格式先呈现大致的图片轮廓,然后随着图片下载的继续,呈现逐渐清晰的图片,这对于移动设备,尤其是慢网络有极大的利好,可带来更好的用户体验。
Android 本身的图片库不支持此格式,但是Fresco支持。使用时,和往常一样,仅仅需要提供一个图片的URI即可,剩下的事情,Fresco会处理。
7. Gif和Webp格式图片的强大支持
  • 加载Gif图和WebP动图在任何一个Android开发者眼里看来都是一件非常头疼的事情。每一帧都是一张很大的Bitmap,每一个动画都有很多帧。Fresco让你没有这些烦恼,它处理好每一帧并管理好你的内存。
  • 支持WebP解码,即使在早先对WebP支持不完善的Android系统上也能正常使用!

在XML中进行属性配置
Fresco有如下几种图层
/* 占位图层,即默认情况下显示的图层 */private final int mPlaceholderImageIndex;/* 进度条图层,即加载过程中的圆形或者线性进度条 */private final int mProgressBarImageIndex;/* 目标显示图层,即加载完成之后显示的图层 */private final int mActualImageIndex;/* 重试图层,即加载失败重试时显示的图层 */private final int mRetryImageIndex;/* 失败图层,即加载失败时显示的图层 */private final int mFailureImageIndex;/* 控制覆盖图层,即遮挡在最上方的图层 */private final int mControllerOverlayIndex;

围绕着这6个图层,我们的SimpleDraweeView布局一般包含如下主要元素
<com.facebook.drawee.view.SimpleDraweeView xmlns:fresco="http://schemas.android.com/apk/res-auto" android:id="@+id/image_fresco2" android:layout_width="100dip" android:layout_height="wrap_content" fresco:actualImageScaleType="centerCrop" fresco:fadeDuration="3000" fresco:failureImage="@mipmap/ic_launcher" fresco:failureImageScaleType="centerCrop" fresco:placeholderImage="@mipmap/ic_launcher" fresco:placeholderImageScaleType="centerCrop" fresco:progressBarAutoRotateInterval="1000" fresco:progressBarImage="@drawable/ani_rotate" fresco:progressBarImageScaleType="centerCrop" fresco:retryImage="@mipmap/ic_launcher" fresco:retryImageScaleType="centerCrop" fresco:backgroundImage="@mipmap/ic_launcher" fresco:overlayImage="@mipmap/ic_launcher" fresco:pressedStateOverlayImage="@mipmap/ic_launcher" fresco:roundAsCircle="false" fresco:roundedCornerRadius="5dip" fresco:roundTopLeft="true" fresco:roundTopRight="true" fresco:roundBottomLeft="true" fresco:roundBottomRight="true" fresco:roundWithOverlayColor="@color/colorAccent" fresco:roundingBorderWidth="2dip" fresco:roundingBorderColor="@color/colorPrimary" fresco:viewAspectRatio="1"/>

属性
作用说明
actualImageScaleType
加载完成的图片的缩放样式
fadeDuration
由进度条和占位符图片渐变过渡到加载完成的图片所使用的时间间隔
failureImage
加载失败所使用的图片
failureImageScaleType
加载失败所使用的图片的缩放样式
placeholderImage
占位符图片
placeholderImageScaleType
占位符图片的缩放样式
progressBarAutoRotateInterval
旋转进度条旋转1圈所需要的时间
progressBarImage
旋转进度条所使用的图片
progressBarImageScaleType
旋转进度条所使用的图片的缩放样式
retryImage
重试所使用的图片
retryImageScaleType
重试所使用的图片的缩放样式
backgroundImage
背景图片
overlayImage
覆盖在加载完成后图片上的叠加图片
pressedStateOverlayImage
按压状态下的叠加图片
roundAsCircle
是否将图片剪切为圆形
roundedCornerRadius
圆角图片时候,圆角的半径大小
roundTopLeft
左上角是否为圆角
roundTopRight
右上角是否为圆角
roundBottomLeft
左下角是否为圆角
roundBottomRight
右下角是否为圆角
roundWithOverlayColor
圆角或圆形图叠加的颜色,只能是颜色
roundingBorderWidth
圆角或圆形图边框的宽度
roundingBorderColor
圆角或圆形图边框的颜色
viewAspectRatio
设置宽高比
这里我就说一下scaleType。与ImageView相比,GenericDraweeView多了一个focusCrop这个属性。这个属性与centerCrop的区别在于前者可以自由定义聚焦点而后者的聚焦点是固定的。DraweeView显示时会尽量以此聚焦点为中心。 聚焦点是以相对坐标形式展现的,比如 (0f, 0f) 是左上角对齐显示,(1f, 1f) 是右下角对齐。这就使得聚焦点位置和具体尺寸无关,这是非常实用的。 如果将聚焦点设置为(0.5f, 0.5f) ,那么它和centerCrop是等价的。
如果要使用此缩放模式,首先在 XML 中指定缩放模式:
fresco:actualImageScaleType="focusCrop"
然后在Java代码中,给你的图片指定聚焦点:
hierarchy.setActualImageFocusPoint(PointF( 1 f, 1 f))

这里有几个注意的地方需要提醒一下大家
  1. SimpleDraweeView的宽高不能同时为wrap_content,需要使用match_parent或者一个固定值。除非你使用viewAspectRatio设置比例,在这种条件下宽、高中的其中一方可以是wrap_content
  1. 使用SimpleDraweeView的时候,facebook官方建议不要再使用ImageView的任何属性,如setImageResource、setBackground、setScaleType等这些ImageView中有但是View中没有的属性
进度条的制作
进度条目前有3种样式选择
系统默认的线性进度条
hierarchy.setProgressBarImage(ProgressBarDrawable())
任意一张图片,使用旋转动画
<?xml version="1.0" encoding="utf-8"?><animated-rotate xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/load_progress_8" android:pivotX="50%" android:pivotY="50%"></animated-rotate>
直接使用该xml

渐进式图片加载
渐进式图片是从模糊到清楚的一种加载模式。fresco仅支持文件类型为JPEG的网络图片,因为本地图片均一次性解码完成,所以本地图片不需要使用渐进式。在fresco中,你可以设置一个清晰度标准,使其在达到这个标准之前一直以占位图显示。


支持图片类型
类型
SCHEME
远程图片
http://, https://
本地文件
file://
Content provider
content://
asset目录下的资源
asset://
res目录下的资源
res://
Uri中指定图片数据
data:mime/type;base64,数据类型必须符合 rfc2397规定 (仅支持 UTF-8)

重试机制
DraweeController controller = Fresco. newDraweeControllerBuilder ()
.setUri(uri)
.setOldController( simpleDraweeView .getController())
.setTapToRetryEnabled( true ).build();

simpleDraweeView .setController(controller);

代码实现:
simpleDraweeView = findViewById(R.id. iv );
RoundingParams roundingParams = new RoundingParams();
roundingParams.setRoundAsCircle( true );

GenericDraweeHierarchy hierarchy = GenericDraweeHierarchyBuilder. newInstance (getResources())
.setRoundingParams(roundingParams)
.setFadeDuration( 5000 )
.build();
simpleDraweeView .setHierarchy( hierarchy );


Picasso,Glide,Fresco的区别
  • Picasso :和Square的网络库一起能发挥最大作用,因为Picasso可以选择将网络请求的缓存部分交给了okhttp实现。使用4.0+系统上的HTTP缓存来代替磁盘缓存.
Picasso 底层是使用OkHttp去下载图片,所以Picasso底层网络协议为Http.
  • Glide:模仿了Picasso的API,而且在它的基础上加了很多的扩展(比如gif等支持),Glide默认的Bitmap格式是RGB_565,比Picasso默认的ARGB_8888格式的内存开销要小一半;Picasso缓存的是全尺寸的(只缓存一种),而Glide缓存的是跟ImageView尺寸相同的(即5656和128128是两个缓存) 。
Glide 底层默认使用的是HttpUrlConnection的方式请求网络,所以Glide的底层网络协议也为Http.
Fresco:最大的优势在于5.0以下(最低2.3)的bitmap加载。在5.0以下系统,Fresco将图片放到一个特别的内存区域(Ashmem区,这个区域没有被统计到App的内存使用里)。当然,在图片不显示的时候,占用的内存会自动被释放。这会使得APP更加流畅,减少因图片内存占用而引发的OOM。为什么说是5.0以下,因为在5.0以后系统默认就是存储在Ashmem区了。
Image pipeline 默认使用HttpURLConnection。应用可以根据自己需求使用不同的网络库。Fresco的Image Pipeline负责图片的获取和管理。图片可以来自远程服务器,本地文件,或者Content Provider,本地资源。压缩后的文件缓存在本地存储中,Bitmap数据缓存在内存中.
功能性 Fresco > Glide > Picasso
包大小 Fresco > Glide > Picasso
主要功能:
共有的功能:根据content生命周期进行图片加载或暂停和恢复,缓存图片到本地。
加载图片格式及大小:
  • Picasso:下载全尺寸图片,load全尺寸图片到imageview上,图片使用ARGB-8888格式。
  • Glide:包含Picasso功能,默认下载不同图片至本地,load 对应imageview尺寸的图片,图片使用ARGB-565格式。
可加载gif、缩略图、视频静态图片、转换字节数组、显示动画。
  • Fresco:结合Picasso、Glide优点,更适用于加载大量图片。另支持渐进式显示图片、WebP格式图片。
对图片转换
  1. Picasso: picasso-transformations,:结合picasso,支持将图片转换为其他形状后显示。
  1. Glide: glide-transformations:结合glide,支持将图片转换为其他形状后显示。
  1. Fresco: android-gpuimage:支持将图片变幻为各种滤镜效果。
总结:
  • Picasso所能实现的功能,Glide都能做,无非是所需的设置不同。但是Picasso体积比起Glide小太多,如果项目中网络请求本身用的就是okhttp或者retrofit(本质还是okhttp),那么建议用Picasso,体积会小很多(Square全家桶的干活)。
  • Glide的好处是大型的图片流,比如gif、Video,如果你们是做美拍、爱拍这种视频类应用,建议使用。
  • Fresco在5.0以下的内存优化非常好,代价就是体积也非常的大,按体积算Fresco>Glide>Picasso不过在使用起来也有些不便(小建议:它只能用内置的一个ImageView来实现这些功能,用起来比较麻烦,我们通常是根据Fresco自己改改,直接使用他的Bitmap层).

加载最先可用的图片
大部分时候,一张图片只有一个 URI。加载它,然后工作完成~
但是假设同一张图片有多个 URI 的情况。比如,你可能上传过一张拍摄的照片。原始图片太大而不能上传,所以图片首先经过了压缩。在这种情况下,首先尝试获取本地压缩后的图片 URI,如果失败的话,尝试获取本地原始图片 URI,如果还是失败的话,尝试获取上传到网络的图片 URI。直接下载我们本地可能已经有了的图片不是一件光彩的事。
Image pipeline 会首先从内存中搜寻图片,然后是磁盘缓存,再然后是网络或其他来源。对于多张图片,不是一张一张按上面的过程去做,而是 pipeline 先检查所有图片是否在内存。只有没在内存被搜寻到的才会寻找磁盘缓存。还没有被搜寻到的,才会进行一个外部请求。
使用时,创建一个image request 数组,然后传给  ControllerBuilder  :

Uri uri1, uri2;ImageRequest request = ImageRequest.fromUri(uri1);ImageRequest request2 = ImageRequest.fromUri(uri2);ImageRequest[] requests = { request1, request2 };DraweeController controller = Fresco.newDraweeControllerBuilder() .setFirstAvailableImageRequests(requests) .setOldController(mSimpleDraweeView.getController()) .build();mSimpleDraweeView.setController(controller);

先显示低分辨率的图,然后是高分辨率的图
假设你要显示一张高分辨率的图,但是这张图下载比较耗时。与其一直显示占位图,你可能想要先下载一个较小的缩略图。
这时,你可以设置两个图片的URI,一个是低分辨率的缩略图,一个是高分辨率的图。 Uri lowResUri, highResUri;DraweeController controller = Fresco.newDraweeControllerBuilder() .setLowResImageRequest(ImageRequest.fromUri(lowResUri)) .setImageRequest(ImageRequest.fromUri(highResUri)) .setOldController(mSimpleDraweeView.getController()) .build();mSimpleDraweeView.setController(controller);
注意:动图无法在低分辨率显示
该如何选择图片加载库?
如果你手中的项目比较老旧,而且代码量较大,你又没什么时间去大改,那么继续维持当前的选择是比较稳妥的办法。如果是新上马的项目,那么UIL由于不再维护、Picasso基本被Glide全方位超越,我推荐使用Glide或Fresco。如果你的App里,图片特别多,而且都是很大、质量很高的图 片,而且你不太在乎App的体积(可能性不大),那么Fresco就是很好的选择了,而Glide相比较Fresco,Glide要轻量一些,而且是Google官方推荐,所以在多数时候,会是开发者的首选。话说回来,如果你对这些图库都不满意,那可以自己写一个,如果可以的话!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值