您的位置:首页 > 移动开发 > Android开发

图片加载神器fresco----fresco的基本使用

2016-09-01 22:35 489 查看
写在前面

库的依赖配置

使用fresco来加载图片
1 在xml中配置SimpleDraweeView的属性

2 如何查找SimpleDraweeView控件中都有哪些可用的自定义属性
首先查看SimpleDraweeView的源码

其次分析fresco如何加载xml配置的属性

1. 写在前面

好久没写博客了,最近在对公司的项目进行重构和优化,针对图片加载框架的修改,原来使用的是Glide,现在改成Facebook的fresco来做对比。先介绍fresco的基本使用。

2. 库的依赖配置

我这里用的IDE是Android Studio,对于库支持的使用配置比较简单,如下:

在module的gradle中加入库的依赖引用。

dependencies {
/************图片加载框架fresco库开始**************/
compile 'com.facebook.fresco:fresco:0.12.0'
/************图片加载框架fresco库结束**************/
}


这样就可以使用fresco库来加载图片了,是不是很简单。

当然fresco库远不止这些,这是一个很强大的库,如要支持webP格式的图片,Gif图片。还可以引入如下的库:

dependencies {
/************图片加载框架fresco库开始**************/

compile 'com.facebook.fresco:fresco:0.12.0'

// 在API < 14的系统如也要支持 webP图片的话加入
compile 'com.facebook.fresco:animated-base-support:0.12.0'
// 支持Gif图片,需加入
compile 'com.facebook.fresco:animated-gif:0.12.0'
// 支持webP图片的动态图,需加入
compile 'com.facebook.fresco:animated-webp:0.12.0'
// 支持webP图片的静态图,需加入
compile 'com.facebook.fresco:webpsupport:0.12.0'

/************图片加载框架fresco库结束**************/
}


webp格式图片,进一步的优化了图片资源的大小,加载的效率更高了,提升了app的性能。

为了迎合官方推广使用Android Studio,这里就不多介绍fresco在Eclipse中的使用,这里附上库的下载包:zip文件

3. 使用fresco来加载图片

首先在加载图片前需要对框架做初始化的操作,通过调用Fresco.initialize方法一次就可以初始化。因为多次调用此方法是一样的,所以作为初始化的地方最好的位置就是 Application的onCreate里:

public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Fresco.initialize(this);
}
}


注意事项:一般情况下这样就可以了,但是对于多进程的应用来说,不同的进程都会执行一次Application的onCreate方法,那就意味着在onCreate里的一些初始化操作会多次执行,多少对于应用的性能是有影响的。那对于多进程环境的应用可以有如下解决方案(伪代码,就是这么随意任性):

public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
String curProcessName = 获取当前进程的名字
String needUseFrescoProcessName = 需要使用fresco组件库来加载图片的进程名字
if(curProcessName.equals(needUseFrescoProcessName)){
// 当前进程就是需要加载fresco组件的进程,才初始化组件
Fresco.initialize(this);
// 同理其它的一些组件也是,如:第三方分享组件,统计组件,支付组件等等
}

}
}


我们先加载一张网络图片,那就需要网络权限,在manifest中加入,别加入自己的Application:

<manifest
...
>
<uses-permission android:name="android.permission.INTERNET" />
<application
...
android:label="@string/app_name"
android:name=".MyApplication"
>
...
</application>
...
</manifest>


fresco为我们提供了一个图片显示控件SimpleDraweeView,这个控件基本上能满足我们绝大多数的需求,使用也很简单:

<com.facebook.drawee.view.SimpleDraweeView
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:id="@+id/sdv_head_image"
android:layout_width="50dp"
android:layout_height="50dp"
fresco:placeholderImage="@drawable/ic_wait_image"
/>


因为要用到控件的自定义属性,所以需要引入自定义的命名空间fresco。

placeholderImage顾名思义,就是图片还在加载,下载的时候,等待期间显示的图片,可以是drawable图片也可以是color颜色。下面来加载一张网络图片:

SimpleDraweeView headImage = (SimpleDraweeView)findViewById(R.id.sdv_head_image);
Uri headUri = Uri.parse("https://raw.githubusercontent.com/facebook/fresco/gh-pages/static/logo.png");
headImage.setUri(headUri);


是不是很简单,只要把图片的地址用Uri包装起来,设置给SimpleDraweeView,fresco就会帮你去显示占位符图片,下载,缓存,在图像不可见的时候及时的回收图片占用的内存。so easy~~

Uri包装不同的图片格式如下:

类型SCHEME示例
远程图片http://, https:// HttpURLConnection 或者参考 使用其他网络加载方案
本地文件file://FileInputStream
Content providercontent://ContentResolver
asset目录下的资源asset://AssetManager
res目录下的资源res://Resources.openRawResource
Uri中指定图片数据data:mime/type;base64,数据类型必须符合 rfc2397规定 (仅支持 UTF-8)

3.1. 在xml中配置SimpleDraweeView的属性

<com.facebook.drawee.view.SimpleDraweeView
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:id="@+id/sdv_head_image"
android:layout_width="20dp"
android:layout_height="20dp"
fresco:fadeDuration="300"
fresco:actualImageScaleType="focusCrop"
fresco:placeholderImage="@color/wait_color"
fresco:placeholderImageScaleType="fitCenter"
fresco:failureImage="@drawable/error"
fresco:failureImageScaleType="centerInside"
fresco:retryImage="@drawable/retrying"
fresco:retryImageScaleType="centerCrop"
fresco:progressBarImage="@drawable/progress_bar"
fresco:progressBarImageScaleType="centerInside"
fresco:progressBarAutoRotateInterval="1000"
fresco:backgroundImage="@color/blue"
fresco:overlayImage="@drawable/watermark"
fresco:pressedStateOverlayImage="@color/red"
fresco:roundAsCircle="false"
fresco:roundedCornerRadius="1dp"
fresco:roundTopLeft="true"
fresco:roundTopRight="false"
fresco:roundBottomLeft="false"
fresco:roundBottomRight="true"
fresco:roundWithOverlayColor="@color/corner_color"
fresco:roundingBorderWidth="2dp"
fresco:roundingBorderColor="@color/border_color"
fresco:viewAspectRatio="1.0"
/>


解释下属性的意思:

属性作用说明
fadeDuration图片渐渐显示的时间,单位毫秒
actualImageScaleType图片的缩放类型,其值有:none, center,centerCrop,focusCrop,centerInside,fitCenter,fitStart,fitEnd,fitXY。Fresco建议使用focusCrop,它和centerCrop类似,centerCrop是居中后裁切掉超多视图容器的部分图片,而focusCrop可以指定一个焦点后进行裁切。
placeholderImage占位符预加载图片,可以是图片、颜色值
placeholderImageScaleType占位符图片的缩放类型,其值同actualImageScaleType一样。
failureImage图片加载失败后显示的错误图片
failureImageScaleType错误图片的缩放类型
retryImage图片加载失败后,显示的重试加载的图片,重试4次后才形式错误的图片
retryImageScaleType重试图片的缩放类型
progressBarImage正在加载图片时的加载进度条图片
progressBarImageScaleType加载进度条图片的缩放类型
progressBarAutoRotateInterval加载进度条自动旋转的间隔时间,单位毫秒
backgroundImage背景图片,最先绘制的图片
overlayImage覆盖在加载完成后图片上的叠加图片
pressedStateOverlayImage按压状态下的叠加图片
roundAsCircle是否为圆形图片
roundedCornerRadius圆角图片时候,圆角的半径大小
roundTopLeft左上角是否为圆角
roundTopRight右上角是否为圆角
roundBottomLeft左下角是否为圆角
roundBottomRight右下角是否为圆角
roundWithOverlayColor圆角或圆形图叠加的颜色,只能是颜色
roundingBorderWidth圆角或圆形图边框的宽度
roundingBorderColor圆角或圆形图边框的颜色
viewAspectRatio控件的宽高比,因为fresco不支持wrap_content, 所以有些需求可以layout_width为具体的值,layout_height为wrap_content,同时设置这个属性的比例值,否则无效不显示
好了xml中的属性配置就介绍完了,相信有些小伙伴会有个疑问,我第一次使用SimpleDraweeView,怎么会知道它会有这么些自定义的属性可以使用呢!

3.2. 如何查找SimpleDraweeView控件中都有哪些可用的自定义属性

首先,查看SimpleDraweeView的源码

public class SimpleDraweeView extends GenericDraweeView {
// ...省略一些代码
public SimpleDraweeView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}

private void init(Context context, @Nullable AttributeSet attrs) {
if (isInEditMode()) {
return;
}
Preconditions.checkNotNull(
sDraweeControllerBuilderSupplier,
"SimpleDraweeView was not initialized!");
mSimpleDraweeControllerBuilder = sDraweeControllerBuilderSupplier.get();

if (attrs != null) {
TypedArray gdhAttrs = context.obtainStyledAttributes(
attrs,
R.styleable.SimpleDraweeView);
try {
if (gdhAttrs.hasValue(R.styleable.SimpleDraweeView_actualImageUri)) {
setImageURI(Uri.parse(gdhAttrs.getString(R.styleable.SimpleDraweeView_actualImageUri)), null);
}
} finally {
gdhAttrs.recycle();
}
}
}
}


很容易就找到了声明属性的属性集:R.styleable.SimpleDraweeView,接下来我们需要找到声明这个属性集合的values.xml,如下:





看这就找到了xml里面配置的所有属性,是不是很简单!细心的小伙伴会发现R.styleable.SimpleDraweeView下定义的属性就一个actualImageUri,其它的属性是定义在R.styleable.GenericDraweeHierarchy下的,不禁心想博主你特么在逗我么!我能说冤枉么(55555~~~),别急小伙伴们,下面就来分析问你解惑,fresco是在哪里为我们加载和解析了我们xml配置的那些属性呢。

其次,分析fresco如何加载xml配置的属性

看SimpleDraweeView的源码会发现,它的父类是GenericDraweeView,我们来跟踪这个父类:

public class GenericDraweeView extends DraweeView<GenericDraweeHierarchy> {
// ...省略一些代码
public GenericDraweeView(Context context, AttributeSet attrs) {
super(context, attrs);
inflateHierarchy(context, attrs);
}

protected void inflateHierarchy(Context context, @Nullable AttributeSet attrs) {
GenericDraweeHierarchyBuilder builder =
GenericDraweeHierarchyInflater.inflateBuilder(context, attrs);
setAspectRatio(builder.getDesiredAspectRatio());
setHierarchy(builder.build());
}
}


可以看到属性的构建交给了GenericDraweeHierarchyInflater.inflateBuilder方法,继续跟踪下去:

public static GenericDraweeHierarchyBuilder inflateBuilder(
Context context,
@Nullable AttributeSet attrs) {
Resources resources = context.getResources();
GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(resources);
return updateBuilder(builder, context, attrs);
}


继续跟踪updateBuilder方法:

public static GenericDraweeHierarchyBuilder updateBuilder(
GenericDraweeHierarchyBuilder builder,
Context context,
@Nullable AttributeSet attrs) {
//  ...省略了一些代码

if (attrs != null) {
TypedArray gdhAttrs = context.obtainStyledAttributes(
attrs,
R.styleable.GenericDraweeHierarchy);
try {
final int indexCount = gdhAttrs.getIndexCount();
for (int i = 0; i < indexCount; i++) {
final int attr = gdhAttrs.getIndex(i);
// most popular ones first
if (attr == R.styleable.GenericDraweeHierarchy_actualImageScaleType) {
builder.setActualImageScaleType(getScaleTypeFromXml(gdhAttrs, attr));

} else if (attr == R.styleable.GenericDraweeHierarchy_placeholderImage) {
builder.setPlaceholderImage(getDrawable(context, gdhAttrs, attr));

}
}
}
}


终于找到梦寐以求的R.styleable.GenericDraweeHierarchy,然后是一个个去遍历获取每个属性的值,设置给GenericDraweeHierarchyBuilder构造器。调用触发是在SimpleDraweeView的构造器里的super(context, attrs),经过层层调用由updateBuilder完成了所有属性的加载和解析赋值。

文章有点长,感谢耐心看完!fresco基本的加载图片的使用就是这样。后面我会陆续写一些重构和优化项目时,使用fresco的一些特性,和Glide框架的对比,优缺点等等内容。希望此文能带给小伙伴们些许帮助。谢谢~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 图片
相关文章推荐