介绍
GitHub源码 (点击查看)
Fresco支持Android2.3(API level 9)及其以上系统。
依赖
由于我用的是android studio所以这里就只是说一下android studio下如何配置,在强大的gradle,只需要一句话搞定,gradle会帮你下载这个Fresco框架,gradle真好,可以自动维护你项目中的框架
compile 'com.facebook.fresco:fresco:0.5.0+'
dependencies {
// 其他依赖
compile 'com.facebook.fresco:fresco:0.12.0'
}
下面的依赖需要根据需求添加:
dependencies {
// 在 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'
compile 'com.facebook.fresco:webpsupport:0.12.0'
// 仅支持 WebP 静态图,需要添加
compile 'com.facebook.fresco:webpsupport:0.12.0'
}
最牛特性 查看
Fresco的image pipeline 【 ˈpaɪplaɪn】 设计
Demo栗子第1颗
fresco搭建开发环境
gradle
compile 'com.facebook.fresco:fresco:0.12.0'
清单文件配置
public class FrescoApp extends Application {
@Override
public void onCreate() {
super.onCreate();
//初始化Fresco框架
Fresco.initialize(this);
}
}
配置权限
<!--网络-->
<uses-permission android:name="android.permission.INTERNET"/>
<!--sd卡-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
布局
<com.facebook.drawee.view.SimpleDraweeView
android:layout_width="100dp"
android:layout_margin="5dp"
android:background="#AEAEAE"
android:src="@mipmap/ic_launcher"
android:id="@+id/image"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:scaleType="centerCrop"
fresco:roundedCornerRadius="10dp"
fresco:roundTopLeft="true"
fresco:roundTopRight="true"
fresco:roundBottomLeft="true"
fresco:roundBottomRight="true"
android:layout_height="100dp" />
编码实现
public class MainActivity extends AppCompatActivity {
private SimpleDraweeView simpleDraweeView;
private String url;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//(fresco:由facebook公司出的,一种图片三级缓存的实现.)
//步骤二。使用fresco加载网络图片
//2.1.准备一个图片的网络地址
url = "http://img3.imgtn.bdimg.com/it/u=3376426628,3397639127&fm=11&gp=0.jpg";
//2.2 布局fresco 的自定义控件 (必须给控件设置大小)
simpleDraweeView = (SimpleDraweeView) findViewById(R.id.image);
//2.4.自定义控件的相关属性 可以设置圆角。
// fresco:roundedCornerRadius="10dp"
// fresco:roundTopLeft="true"
// fresco:roundTopRight="true"
// fresco:roundBottomLeft="true"
// fresco:roundBottomRight="true"
}
public void showImage(View view) {
//2.3.加载图片
simpleDraweeView.setImageURI(url);
}
}
Demo栗子第2颗
如果你仅仅是想简单下载一张网络图片,在下载完成之前,显示一张占位图,那么简单使用 SimpleDraweeView 即可。
在加载图片之前,你必须初始化Fresco类。你只需要调用Fresco.initialize一次即可完成初始化,在 Application 里面做这件事再适合不过了(如下面的代码),注意多次的调用初始化是无意义的。
[MyApplication.java]
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Fresco.initialize(this);
}
}
做完上面的工作后,你需要在 AndroidManifest.xml 中指定你的 Application 类。为了下载网络图片,请确认你声明了网络请求的权限。
<manifest
...
>
<uses-permission android:name="android.permission.INTERNET" />
<application
...
android:label="@string/app_name"
android:name=".MyApplication"
>
...
</application>
...
</manifest>
在xml布局文件中, 加入命名空间:
<!-- 其他元素-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent">
加入SimpleDraweeView:
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/my_image_view"
android:layout_width="130dp"
android:layout_height="130dp"
fresco:placeholderImage="@drawable/my_drawable"
/>
开始加载图片:
Uri uri = Uri.parse("https://raw.githubusercontent.com/facebook/fresco/gh-pages/static/logo.png");
SimpleDraweeView draweeView = (SimpleDraweeView) findViewById(R.id.my_image_view);
draweeView.setImageURI(uri);
方法栗子:
SimpleDraweeView控件
SimpleDraweeView这个控件了,显示图片的时候直接写了一个setImageURI(uri)
在xml中引入SimpleDraweeView
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/user_avator"
android:layout_width="50dp"
android:layout_height="50dp"
fresco:roundAsCircle="true"
fresco:roundedCornerRadius="180dp"
fresco:actualImageScaleType="focusCrop"
android:layout_centerVertical="true" />
注意:1、属性中存在fresco:开头的声明。这个是fresco的自定义属性,如果我们需要使用其自定义属性,必须在我们的xml根布局中添加声明/命名空间
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
2、配置网络权限
3、在Java代码中开始加载图片
Uri uri = Uri.parse("https://raw.githubusercontent.com/static/fresco-logo.png");
SimpleDraweeView draweeView = (SimpleDraweeView) findViewById(R.id.my_image_view);
draweeView.setImageURI(uri);
接下来详细研究其用法:
URIs的使用:
类型 Scheme 示例
远程图片 http://, https:// HttpURLConnection 或者参考 使用其他网络加载方案
本地文件 file:// FileInputStream
Content provider content:// ContentResolver
asset目录下的资源 asset:// AssetManager
res目录下的资源 res:// Resources.openRawResource
res 示例:Uri uri = Uri.parse("res://包名(实际可以是任何字符串甚至留空)/" + R.drawable.ic_launcher);
注意:Fresco 不支持 相对路径的URI. 所有的URI都必须是绝对路径,并且带上该URI的scheme。
在XML中使用SimpleDraweeView:
给出一个完整的示例:
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/my_image_view"
android:layout_width="20dp" / 不支持wrap_content 如果要设置宽高比, 需要在Java代码中指定setAspectRatio(1.33f);
android:layout_height="20dp" // 不支持wrap_content
fresco:fadeDuration="300"//渐进时间
fresco:actualImageScaleType="focusCrop" // 设置图片缩放. 通常使用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"
/>
说明:必须声明 android:layout_width 和 android:layout_height,否则将无法正确加载图像,另外不支持 wrap_content 属性,但也有例外的时候,如果想固定控件的宽高比,则可以使用wrap_content,并通过在xml代码中设置fresco:viewAspectRatio=”小数”或者在Java代码中设置mSimpleDraweeView.setAspectRatio(1.33f);即可。
在Java中自定义显示图
一般情况下,在XML设置显示效果即可, 如果想更多定制化,可以这样:
创建一个 builder 然后设置给 SimpleDraweeView:
List<Drawable> backgroundsList;
List<Drawable> overlaysList;
GenericDraweeHierarchyBuilder builder =
new GenericDraweeHierarchyBuilder(getResources());
GenericDraweeHierarchy hierarchy = builder
.setFadeDuration(300)
.setPlaceholderImage(new MyCustomDrawable())
.setBackgrounds(backgroundList)
.setOverlays(overlaysList)
.build();
mSimpleDraweeView.setHierarchy(hierarchy);
注意:请不要多次调用setHierarchy,即使这个View是可回收的。创建 DraweeHierarchy 的较为耗时的一个过程,应该多次利用。
- 修改 DraweeHierarchy
DraweeHierarchy 的一些属性可以在运行时改变。
要改变这些属性,首先获取一个引用:
GenericDraweeHierarchy hierarchy = mSimpleDraweeView.getHierarchy();
- 修改占位图
修改占位图为资源id:hierarchy.setPlaceholderImage(R.drawable.placeholderId);
或者修改为一个 Drawable:Drawable drawable; hierarchy.setPlaceholderImage(drawable);
- 修改缩放类型
hierarchy.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_INSIDE);
如果你选择缩放类型为 focusCrop,需要指定一个居中点:hierarchy.setActualImageFocusPoint(point);
- 修改图片尺寸
Uri uri = "file:///mnt/sdcard/MyApp/myfile.jpg";
int width = 50, height = 50;
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
.setResizeOptions(new ResizeOptions(width, height))
.build();
PipelineDraweeController controller = Fresco.newDraweeControllerBuilder()
.setOldController(mDraweeView.getController())
.setImageRequest(request)
.build();
mSimpleDraweeView.setController(controller);
- 自动旋转
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
.setAutoRotateEnabled(true)
.build();
setController(controller)方法加载图片
DraweeController controller = Fresco.newDraweeControllerBuilder().setUri(uri).build();
imageView.setController(controller);
当然如果你想监听加载的过程,就加一个ControllerListen
ControllerListener listener = new BaseControllerListener(){
@Override
public void onFinalImageSet(String id, Object imageInfo, Animatable animatable) {
super.onFinalImageSet(id, imageInfo, animatable);
}
@Override
public void onFailure(String id, Throwable throwable) {
super.onFailure(id, throwable);
}
@Override
public void onIntermediateImageFailed(String id, Throwable throwable) {
super.onIntermediateImageFailed(id, throwable);
}
};
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(uri)
.setControllerListener(listener)
.build();
imageView.setController(controller);
图片加载成功或者失败,会执行里面的方法,其中图片加载成功时会执行onFinalImageSet方法,图片加载失败时会执行onFailure方法,如果图片设置渐进式,onIntermediateImageFailed会被回调
说完了如何加载uri之后,如何实现在xml中的效果呢?我们继续在java代码中实现xml的效果
GenericDraweeHierarchy hierarchy = new GenericDraweeHierarchyBuilder(getResources())
.setFadeDuration(300)
.setBackground(getDrawable(R.drawable.ic_launcher))
.setPlaceholderImage(getDrawable(R.drawable.ic_launcher))
.setFailureImage(getDrawable(R.drawable.ic_launcher))
.build();
imageView.setHierarchy(hierarchy);
方法很多,你在xml中用到的都可以在这里设置,有些在xml中不能设置的在这里也是可以的,例如,我可以设置多张背景图片,我可以设置多张叠加图,这里都可以帮你实现,是不是很强大啊,想不想拿到特权了一样呢!但是DraweeHiererchy创建时比较耗时,所以要多次利用
GenericDraweeHierarchy hierarchy1 = imageView.getHierarchy();
首先是渐进式图片加载,这方面的功能充分考虑了网络比较慢的情况下,用户不至于一致在等,最起码能看到模糊的照片,这个所谓的渐进式加载就是说用户从图片加载之后,图片会从模糊到清晰的一个渐变过程,当然这个过程仅限于从网络加载图片,本地或者缓存等地方的图片也不需要渐进式加载,没有意义
ProgressiveJpegConfig config = new ProgressiveJpegConfig() {
@Override
public int getNextScanNumberToDecode(int i) {
return 0;
}
@Override
public QualityInfo getQualityInfo(int i) {
return null;
}
};
ImagePipelineConfig imagePipelineConfig = ImagePipelineConfig.newBuilder(this)
.setProgressiveJpegConfig(config)
.build();
Fresco.initialize(getApplicationContext(),imagePipelineConfig);
当然你也可以使用ProgressiveJpegConfig config1= new SimpleProgressiveJpegConfig(list,2);
<pre name="code" class="java">FLog.setMinimumLoggingLevel(FLog.VERBOSE);
Set<RequestListener> listeners = new HashSet<>();
listeners.add(new RequestLoggingListener());
ImagePipelineConfig config = ImagePipelineConfig.newBuilder(this)
.setRequestListeners(listeners)
.build();
Fresco.initialize(this, config);
setContentView(R.layout.activity_main);
mProgressiveJpegView = (SimpleDraweeView) findViewById(R.id.my_image_view);
Uri uri = Uri.parse("http://pooyak.com/p/progjpeg/jpegload.cgi?o=1");
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
.setProgressiveRenderingEnabled(true)
.build();
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setImageRequest(request)
.build();
mProgressiveJpegView.setController(controller);
ImageRequest request = ImageRequestBuilder
.newBuilderWithSource(uri)
.setProgressiveRenderingEnabled(true)
.build();
PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder()
.setImageRequest(request)
.setOldController(imageView.getController())
.build();
imageView.setController(controller);
个人认为这个框架最巧妙的地方,就是把bitmap保存到ashmen,不会启动gc,使的界面不会因为gc而卡死,Fresco使用三级缓存,第一级缓存就是保存bitmap,第二级缓存保存在内存,但是没有解码,使用时需要界面,第三级缓存就是保存在本地文件,同样文件也未解码,使用的时候要先解码啦!