引入Fresco的原因:
性能方面:
目前项目中使用的Universal-Image-Loader(简称UIL)是一个比较强大的图片加载框架.在java层有非常丰富的加载,缩放,缓存逻辑,可以满足目前项目所有需要.但是其bitmap在内存缓存这一级依然使用javaheap,在控件大小未能获取到时(页面oncreat时加载图片),创建的bitmap是以原始图片的宽高为标准生成的(不超过config中的默认值-屏幕宽高),导致非常占用内存,特别在列表滑动,和viewpager滑动时,频繁gc会造成卡顿,甚至直接crash.
Fresco在5.0一下系统上将bitmap所占用的内存放在了匿名共享内存.(关于匿名共享内存http://blog.csdn.net/luoshengyang/article/details/6651971),从根本上解决了bitmap引发gc和oom的问题.
示例:
使用UIL和Fresco加载同一张网络图片.
加载前:
使用Fresco加载以后:
使用UIL加载以后
功能方面:
除了满足UIL的功能外,Fresco还有以下功能:
1.网络图片渐进式加载.
2.GIF,WebP的加载
3.自带的圆角处理,不用重新生成bitmap.
4.更多配置可以在xml中完成.
核心内容:
Drawees-负责图片的展示
图片展示控件,可以对图片加载前/中/后进行不同的样式展现.对展示的图片进行修改,传递加载结果信息,
Image pipeline -负责图片的获取
主要是3级缓存的控制.可以自定义使用的网络加载层(默认HttpUrlConnection)
使用方法
引入项目:
compile'com.facebook.fresco:fresco:0.6.0+'
在Application中初始化:
通用/简单初始化
Fresco.initialize(this);
若使用渐进式加载功能,初始化
ImagePipelineConfigimagePipelineConfig = ImagePipelineConfig.newBuilder(this)
.setProgressiveJpegConfig(new SimpleProgressiveJpegConfig())
.build();
Fresco.initialize(this,imagePipelineConfig);
普通加载网络图片:
xml中
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/my_image_view"
android:layout_width="20dp"
android:layout_height="20dp"
fresco:placeholderImage="@drawable/my_drawable"
/>
java中
Uri uri = Uri.parse("https://raw.githubusercontent.com/facebook/fresco/gh-pages/static/fresco-logo.png");
SimpleDraweeViewdraweeView = (SimpleDraweeView) findViewById(R.id.my_image_view);
draweeView.setImageURI(uri);
注意:
SimpleDraweeView的宽高必须是可以确定的:
fillparent和xxdp都可以.
如果有一面为wrapcontent,则必须指定宽高比:
mSimpleDraweeView.setAspectRatio(1.33f);
常用的xml配置项:
fresco:actualImageScaleType=“focusCrop" //实际图片缩放形式,默认centerCrop
fresco:placeholderImage=“@color/wait_color" //加载中占位图
fresco:placeholderImageScaleType=“fitCenter" //加载中占位图的缩放形式,默认centerInside
fresco:failureImage=“@drawable/error" //加载失败的图
fresco:failureImageScaleType=“centerInside" 加载失败的图缩放形式,默认centerInside
fresco:roundAsCircle=“true” //显示为圆形
以下代码中使用的FrescoImageUtil封装了一些转换常用图片地址为URI以及简单加载网络图片的方法.
获取图片加载监听
ControllerListenercontrollerListener = new BaseControllerListener<ImageInfo>() {
@Override
public void onFinalImageSet(
String id,
@Nullable ImageInfo imageInfo,
@Nullable Animatable anim) {
//加载成功,此处可以获得bitmap的宽高等信息
}
@Override
public void onIntermediateImageSet(Stringid, @Nullable ImageInfo imageInfo) {
//加载渐进式图片会回调
}
@Override
public void onFailure(String id, Throwablethrowable) {
//加载失败
}
};
<p>Uri uri;</p><p>DraweeControllercontroller = Fresco.newControllerBuilder()</p><p> .setControllerListener(controllerListener)</p><p> .setUri(uri);</p><p> .build();</p><p>mSimpleDraweeView.setController(controller);</p>
渐进式加载图片
即加载过程中图片会从模糊到清晰逐级展现.
除初始化时需要自定义的ImagePipelineConfig以外.还需要:
ImageRequestrequest = ImageRequestBuilder
.newBuilderWithSource(FrescoImageUtil.getUriFromNet(url))
.setProgressiveRenderingEnabled(true)
.build();
PipelineDraweeController controller =(PipelineDraweeController) Fresco.newDraweeControllerBuilder()
.setImageRequest(request)
.setOldController(simpleDraweeView.getController())
.build();
simpleDraweeView.setController(controller);
项目中的特殊应用:
使用后处理器Postprocessor对显示的网络图片进行模糊处理:
PostprocessorblurPostprocessor = new BasePostprocessor() {
@Override
public String getName() {
return"blurPostprocessor";
}
@Override
public void process(Bitmap bitmap){
for (int x = 0; x <bitmap.getWidth(); x += 2) {
for (int y = 0; y <bitmap.getHeight(); y += 2) {
bitmap.setPixel(x, y,Color.RED);
}
}
final RenderScript rs =RenderScript.create(ProductListActivity.this);
final Allocation input =Allocation.createFromBitmap(rs, bitmap, Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT);
final Allocation output =Allocation.createTyped(rs, input.getType());
final ScriptIntrinsicBlurscript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
script.setRadius(20);
script.setInput(input);
script.forEach(output);
output.copyTo(bitmap);
}
@Override
public void process(BitmapdestBitmap, Bitmap sourceBitmap) {
super.process(destBitmap,sourceBitmap);
}
@Override
publicCloseableReference<Bitmap> process(Bitmap sourceBitmap,PlatformBitmapFactory bitmapFactory) {
return super.process(sourceBitmap,bitmapFactory);
}
};
ImageRequestrequest =ImageRequestBuilder.newBuilderWithSource(FrescoImageUtil.getUriFromNet(brandDetailInfo.mobileImageOne))
.setPostprocessor(blurPostprocessor)
.build();
PipelineDraweeController controller =(PipelineDraweeController)
Fresco.newDraweeControllerBuilder()
.setImageRequest(request)
.setOldController(bandImage.getController())
.build();
bandImage.setController(controller);
从缓存中获得bitmap
ImageRequestimageRequest =ImageRequest.fromUri(FrescoImageUtil.getUriFromNet(thumbImgUrl));
ImagePipeline imagePipeline =Fresco.getImagePipeline();
DataSource<CloseableReference<CloseableImage>> dataSource =
imagePipeline.fetchImageFromBitmapCache(imageRequest, null);
dataSource.subscribe(newBaseBitmapDataSubscriber() {
@Override
public voidonNewResultImpl(@Nullable Bitmap bitmap) {
if (bitmap != null) {
//由于返回的bitmap在方法执行完后就会回收,所以需要copy一份出来进行分享操作
sendTextMsgToWx(getBitmapForWxThumb(bitmap), title, content, weburl,isToCircle);
} else {
sendTextMsgToWx(null,title, content, weburl, isToCircle);
}
}
@Override
public voidonFailureImpl(DataSource dataSource) {
sendTextMsgToWx(null,title, content, weburl, isToCircle);
}
},CallerThreadExecutor.getInstance());