一、引言
在我们平时加载图片(不管是下载还是加载本地图片…..)的时候,我们经常会遇到这样一个需求,那就是当图片正在加载时应该呈现正在加载时的图像,当图片加载失败时应该呈现图片加载时的图像,当我们重新加载这张图片时,应该呈现重试时图像,直到这张图片加载完成。记得最开始是用Asynctack写的,后来用上了Universal Image Loader,UIL用了几年,这东东很久没更新了,近两年选用Fresco或者Glide。
Glide因为其体积小、缓存机制强大等优点,受到了广大程序员的青睐;Fresco虽然体积比较大,缓存机制也没有Glide强大,但它胜在拥有一些炫酷的效果(进度条、淡入效果)等,也有很多人在使用。Fresco这个框架出的有一阵子了,也是现在非常火的一款图片加载框架,Fresco中实现了各种加载过程以及加载后的图片绘制,整体还是很强大的。听说内部实现的挺牛逼的,虽然自己还没研究原理,不过先介绍下基本功能的使用,感受了一下这个框架的强大之处。
二、Fresco介绍
Fresco是美国的Facebook公司出品的,功能全,代码健壮,是一款开源框架,号称是目前最强的Android图片加载库,在内存方面的表现极为优秀。看看有哪些优缺点:
优点:
- 使用简便,学习成本低
- 十分强大,使用起来非常流畅,内存管理不用愁,不用担心OOM
- 自带加载时淡入效果,开发起来不费劲
- 图片加载时可在布局中直接设置加载动画等等,代码量大大减少
缺点:
- 必须使用fresco自定义的控件,如果需求更换,想要更换其他图片加载框架会有一定的麻烦,比如必须要改布局
- 方法数太多,多达近4k方法,整项目方法数超过65k,不得不分包,而且打包之后整个项目整整多了3M,确实大得很
- 必须全套使用fresco的图片加载
总之,虽然有缺点,但在我的印象中,fresco就是图片加载处理的专业管家,几乎一切繁杂的事情它都帮你处理妥当,用起来简直贴心。
GitHub : Fresco
也有不少热心的开发者基于Fresco做了一些封装并开放给他人使用:
GitHub : fresco-helper
三、Fresco应用
Fresco的用处很强大,这里只介绍一些最基本的应用,若要了解更多,可以去官网或Fresco中文网看看。
3.1 引入依赖
在AS的build.gradle中的dependencies下直接添加如下代码:
//Fresco
implementation 'com.facebook.fresco:fresco:+' //V1.10.0
同时可以根据项目需求选择添加如下依赖:
// 支持 GIF 动图,需要添加
compile 'com.facebook.fresco:animated-gif:+'
// 支持 WebP (静态图+动图),需要添加
compile 'com.facebook.fresco:animated-webp:+'
compile 'com.facebook.fresco:webpsupport:+'
// 仅支持 WebP 静态图,需要添加
compile 'com.facebook.fresco:webpsupport:+'
3.2 初始化
创建Application类的onCreate方法里初始包:Fresco.initialize(this);
public class FrescoApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//初始化fresco包
Fresco.initialize(this);
}
}
3.3 布局
用Fresco不爽的地方就是什么都要按照人家的要求来,如控件名字,命名空间都要听人家的。Fresco不同于其它几个图片加载库,它是基于自定义控件的,要使用控件SimpleDraweeView来显示图片:
<com.facebook.drawee.view.SimpleDraweeView
android:layout_width="400dp"
android:layout_height="match_parent"
android:id="@+id/imageDraweeView"
fresco:placeholderImage="@mipmap/ic_launcher"/>
另外,Fresco还提供丰富的可配置功能,当图片加载失败之后我们也是需要有默认图片去进行填充的。实现起来也比较简单:
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/failureImageDraweeView"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_margin="5dp"
fresco:failureImage="@drawable/error"
fresco:failureImageScaleType="centerInside"/>
3.4 UI使用
在activity中加载图片显示如下:
private SimpleDraweeView sdv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Fresco.initialize(this);//Fresco的初始化,必须调用在setContentView之前
setContentView(R.layout.activity_main);
sdv = (SimpleDraweeView) findViewById(R.id.imageDraweeView);
Uri uri = Uri.parse("http://xmamiga.com/uploadImages/test.jpg");
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(uri)
.setAutoPlayAnimations(true)
.build();
sdv.setController(controller);
}
//点击事件加载网络图片代码
public void loadInternetImage(View view){
Uri uri = Uri.parse("http://xmamiga.com/uploadImages/test.jpg");
SimpleDraweeView draweeView = (SimpleDraweeView) findViewById(R.id.my_image_view);
draweeView.setImageURI(uri);
}
很简单吧,剩下的,Fresco会替你完成,比如:显示占位图直到加载完成;下载图片;缓存图片;图片不再显示时,从内存中移除等等等等。当然,有时候需要加载很多图片,这个时候如果网络情况不是很好的情况下,一直显示占位图,体验也不是很好,我们可以先显示一个低分辨率的图片,等到大图加载完成之后,再显示真正的图片。
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setLowResImageRequest(ImageRequest.fromUri(lowResUri))
.setImageRequest(ImageRequest.fromUri(highResUri))
.setOldController(draweeView.getController())
.build();
draweeView.setController(controller);
如果想监听加载的过程,就加一个ControllerListen,在ControllerListener中可以对下载过程进行监听。代码如下
//写一个监听器 监听图片加载
ControllerListener listener = new BaseControllerListener(){
/**
* 当图片加载成功时会执行的方法
* @param id
* @param imageInfo
* @param animatable
*/
@Override
public void onFinalImageSet(String id, Object imageInfo, Animatable animatable) {
super.onFinalImageSet(id, imageInfo, animatable);
}
/**
* 图片加载失败时调用的方法
* @param id
* @param throwable
*/
@Override
public void onFailure(String id, Throwable throwable) {
super.onFailure(id, throwable);
}
/**
* 如果图片使用渐进式,这个方法将会被回调
* @param id
* @param throwable
*/
@Override
public void onIntermediateImageFailed(String id, Throwable throwable) {
super.onIntermediateImageFailed(id, throwable);
}
};
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(uri)
.setAutoPlayAnimations(true)
.setControllerListener(listener)
.build();
sdv.setController(controller);
3.5 更多属性
drawee支持如下属性:
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/id_main_sdv"
fresco:actualImageScaleType="focusCrop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp" //加载得到的图片的缩放类型
fresco:fadeDuration="1000" //进度条,占位图片消失,加载图片展现的时间间隔
fresco:failureImage="@drawable/imgbg" //加载失败之后显示的图片
fresco:failureImageScaleType="centerInside" //图片缩放类型
fresco:placeholderImage="@drawable/imgbg" //占位图片(未加载之前显示的图片)
fresco:placeholderImageScaleType="fitCenter"
fresco:progressBarAutoRotateInterval="1000" //加载进度条图片旋转周期
fresco:progressBarImage="@drawable/progress_bar" //加载进度条图片
fresco:progressBarImageScaleType="centerInside"
fresco:retryImage="@mipmap/ic_launcher" //提示重新加载的图片资源
fresco:retryImageScaleType="centerCrop"
fresco:backgroundImage="@color/colorWhite" //背景图片
fresco:roundAsCircle="false" //是否要将图片剪切成圆形
fresco:viewAspectRatio="1" //图片宽高比
fresco:overlayImage="@drawable/overlay" //在图片上方覆盖一个图片资源
fresco:pressedStateOverlayImage="@color/colorBlack"
fresco:roundedCornerRadius="20dp" //圆角角度,
fresco:roundTopLeft="true" //设置哪个角需要变成圆角
fresco:roundTopRight="false"
fresco:roundBottomLeft="false"
fresco:roundBottomRight="true"
fresco:roundWithOverlayColor="@color/colorWhite" //圆角部分填充色
fresco:roundingBorderWidth="2dp" //边框宽度
fresco:roundingBorderColor="@color/colorBlack" //边框填充色
/>
3.6 支持的URI
Fresco 支持许多URI格式。但不支持相对路径的URI,所有的URI都必须是绝对路径,并且带上该URI的scheme。
res 示例:
Uri uri = Uri.parse("res://包名(实际可以是任何字符串甚至留空)/" + R.drawable.ic_launcher);
3.7 注意事项
- SimpleDraweeView控件的宽高不能设置为wrap_content,只能是match_parent、具体值或使用viewAspectRatio属性设置宽高比
- 如果在一个页面中加载多张图片,不要将SimpleDraweeView直接放在ScollView中,建议使用RecyclerView、ListView或GridView,因为ScrollView中的SimpleDraweeView会持有内存直到Activity或Fragment销毁
- 使用SimpleDraweeView时,不要使用imageView中有、View中没有的属性
四、总结
如果只是想对网络图片进行加载以及显示一些特效,那么SimpleDraweeView就基本上可以满足需求了;Fresco是使用Image Pipeline来实现对图片的管理和获取的,SimpleDraweeView是对ImageView的一个封装,并且内部使用了Image Pipeline管理图片的思想和方式。总之,Fresco太强大太优秀了,上面所描述的只是沧海一栗。