Android四大图片缓存框架之-Fresco(一)
本文来自于Fresco中文文档,这仅仅是自己的学习笔记!!!大牛绕路,放我我。
关于Fresco的介绍,请查看链接
关于android图片缓存,这是一个android程序员必须了解的。关于四大图片缓存框架的特性与对比,请移步MDCC传送门
首先说明,本文的大多数内容来自于官方文档,请勿喷!!!
那么今天我们就来了解下Fresco,作为FB出版的开源项目,据说是目前最好的缓存框架。
那么我们就先来了解下Fresco是个什么。
- Fresco是一个强大的图片加载组件
- Fresco中设计有一个叫做image pipeline 的模块。他负责从网络,从本地文件系统,本地资源加载图片。为了最大限度上节省空间和CPU时间,它含有3级缓存的设计(额,没三级能拿出手?)
- Fresco中设计有一个叫做Drawees模块,方便地显示loading图,当图片不再显示在屏幕上时,及时地释放内存和空间占用。
- Fresco支持Android2.3及以上系统
简单的看下使用SimpleDraweeView显示一张占位图。在XML文件中加入
<com.facebook.drawee.view.SimpleDraweeView android:id="@+id/my_image_view" android:layout_width="200dp" android:layout_height="200dp" android:layout_centerInParent="true" > </com.facebook.drawee.view.SimpleDraweeView>
在代码中设置Uri,
draweeView = (SimpleDraweeView) findViewById(R.id.my_image_view); Uri uri = Uri.parse("https://raw.githubusercontent.com/facebook/fresco/gh-pages/static/fresco-logo.png");// draweeView.setController(draweeController); draweeView.setImageURI(uri);
最后添加网络权限,就可以了。我们在来看下这里的Uri支持什么格式:
- 远程图片 http:// 或者 https://
- 本地文件 file://
- Content Provider content://
- asset目录下的资源 asset://
- res目录下的资源 res://包名/+R……
接下来便详细的介绍Drawee
举个栗子:
<com.facebook.drawee.view.SimpleDraweeView android:id="@+id/my_image_view" 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" />
上面这个是官方的栗子,上面有所有的属性,我们就来看看,这些属性代表什么意思,
- layout_width和layout_height 不支持warp_content,但是可以通过setAspectRetio();来设置宽高比
- fadeDuration() 淡..时间
- actualImageScaleType 设置图片缩放,通常使用foucsCrop,该属性值会通过算法把人头像放在中间,关于缩放,请移步黑洞
- placeholderImage 下载成功之前显示的图片
- placeholderImageScaleType
- failureImage 加载失败时显示的图片
- failureImageScaleType
- retryImage 加载失败,提示用户点击重新加载的图片
- retryImageScaleType
- progressBarImage 提示 用户正在加载,和进度无关
- progressBarImageScaleType
- progressBarAutoRotateInterval 图片自动旋转的时间间隔
- backgroundImage 背景
- overlayImage 叠加图
- pressedStateOverlayImage 按下时候的叠加图
- roundAsCircle 是否涉及圆圈
- roundedCornerRadius 圆角
- roundTopLeft、roundTopRight….. 分别设置4个角不同半径,设置为true以后可以再代码中设置角度。通过RoundingParams的setConnersRadii()方法
public RoundingParams setCornersRadii(float topLeft, float topRight, float bottomRight, float bottomLeft) { float[] radii = this.getOrCreateRoundedCornersRadii(); radii[0] = radii[1] = topLeft; radii[2] = radii[3] = topRight; radii[4] = radii[5] = bottomRight; radii[6] = radii[7] = bottomLeft; return this; }
- roundWithOverlayColor,边框的叠加颜色
- roundingBorderWidth 边框宽度
roundingBorderColor 边框颜色
我们看到,仅仅靠xml文件的属性,功能就已经很强大了。我们通过什么来在代码中设置各种效果呢?看代码
GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(getResources());GenericDraweeHierarchy hierarchy = builder .setFadeDuration(300) .setPlaceholderImage(new MyCustomDrawable()) .setBackgrounds(backgroundList) .setOverlays(overlaysList) .build();mSimpleDraweeView.setHierarchy(hierarchy);
DraweeHierarchy的一些属性可以在运行时改变。
GenericDraweeHierarchy hierarchy =mSimpleDraweeView.getHierarchy();hierarchy.setPlaceholderImage(R.drawable.placeholderId);
注意:对于同一个View,不要多次调用setHierarchy。
我们看看GenericDraweeHierarchy提供了哪些set方法
看到这里有相当多的drawable啊。我们在来看看,Fresco源码中有哪些Drawable,
我们在set…(new ..Drawable),就可以轻松使用了。我们以ProgressBarDrawable为例,看看他提供了哪些方法。
,看起来还是很强大的。当然,我们可以自定义Drawable,关于自定义Drawable,我这里就不再说了,网上还是很多的。
我们在来看看ControllerBuilder,从字面上就可以看出,这个可以对图片做出一些控制。
ControllerListener listener = new BaseControllerListener() {...}DraweeController controller = Fresco.newDraweeControllerBuilder() .setUri(uri) .setTapToRetryEnabled(true) .setOldController(mSimpleDraweeView.getController()) .setControllerListener(listener) .build();mSimpleDraweeView.setController(controller);
在指定一个新的controller的时候,使用setOldController,可以节省不必要的内存分配。
我们来看看Fresco.newDraweeControllerBuilder()有哪些set方法。
自定义图片加载请求
Uri uri;Postprocessor myPostprocessor = new Postprocessor() { ... }ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri) .setPostprocessor(myPostprocessor) .build();DraweeController controller = Fresco.newDraweeControllerBuilder() .setImageRequest(request) .setOldController(mSimpleDraweeView.getController()) // 其他设置 .build();
渐进式JPEG图
ProgressiveJpegConfig pjpegConfig = new ProgressiveJpegConfig() { @Override public int getNextScanNumberToDecode(int scanNumber) { return scanNumber + 2; } public QualityInfo getQualityInfo(int scanNumber) { boolean isGoodEnough = (scanNumber >= 5); return ImmutableQualityInfo.of(scanNumber, isGoodEnough, false); }}ImagePipelineConfig config = ImagePipelineConfig.newBuilder() .setProgressiveJpegConfig(pjpeg) .build();
Uri uri;ImageRequest request = ImageRequestBuilder .newBuilderWithSource(uri) .setProgressiveRenderingEnabled(true) .build();PipelineDraweeController controller = Fresco.newControllerBuilder() .setImageRequest(requests) .setOldController(mSimpleDraweeView.getController()) .build();mSimpleDraweeView.setController(controller);
Gif动态图
Uri uri;ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri) . // other setters .build();DraweeController controller = Fresco.newDraweeControllerBuilder() .setImageRequest(request) .setAutoPlayAnimations(true) . // other setters .build();mSimpleDraweeView.setController(controller);
手动控制动态图播放
ControllerListener controllerListener = new BaseControllerListener<ImageInfo>() { @Override public void onFinalImageSet( String id, @Nullable ImageInfo imageInfo, @Nullable Animatable anim) { if (anim != null) { // app-specific logic to enable animation starting anim.start(); }};Uri uri;DraweeController controller = Fresco.newDraweeControllerBuilder() .setUri(uri) .setControllerListener(controllerListener) // other setters .build();mSimpleDraweeView.setController(controller);
使用动画
Animatable animation = mSimpleDraweeView.getController().getAnimatable();if (animation != null) { // 开始播放 animation.start(); // 一段时间之后,根据业务逻辑,停止播放 animation.stop();}
多图请求以及图片复用
Uri lowResUri, highResUri;DraweeController controller = Fresco.newDraweeControllerBuilder() .setLowResImageRequest(ImageRequest.fromUri(lowResUri)) .setImageRequest(ImageRequest.fromUri(highResUri)) .setOldController(mSimpleDraweeView.getController()) .build();mSimpleDraweeView.setController(controller);
缩略图预览
Uri uri;ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri) .setLocalThumbnailPreviewsEnabled(true) .build();DraweeController controller = Fresco.newDraweeControllerBuilder() .setImageRequest(request) .setOldController(mSimpleDraweeView.getController()) .build();mSimpleDraweeView.setController(controller);
本地图片复用
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);
监听下载事件
ControllerListener controllerListener = new BaseControllerListener<ImageInfo>() { @Override public void onFinalImageSet( String id, @Nullable ImageInfo imageInfo, @Nullable Animatable anim) { if (imageInfo == null) { return; } QualityInfo qualityInfo = imageInfo.getQualityInfo(); FLog.d("Final image received! " + "Size %d x %d", "Quality level %d, good enough: %s, full quality: %s", imageInfo.getWidth(), imageInfo.getHeight(), qualityInfo.getQuality(), qualityInfo.isOfGoodEnoughQuality(), qualityInfo.isOfFullQuality()); } @Override public void onIntermediateImageSet(String id, @Nullable ImageInfo imageInfo) { FLog.d("Intermediate image received"); } @Override public void onFailure(String id, Throwable throwable) { FLog.e(getClass(), throwable, "Error loading %s", id) }};Uri uri;DraweeController controller = Fresco.newControllerBuilder() .setControllerListener(controllerListener) .setUri(uri); // other setters .build();mSimpleDraweeView.setController(controller);
修改图片尺寸
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();
图片的修改。后处理器
Uri uri;Postprocessor redMeshPostprocessor = new BasePostprocessor() { @Override public String getName() { return "redMeshPostprocessor"; } @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); } } }}ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri) .setPostprocessor(redMeshPostprocessor) .build();PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder() .setImageRequest(request) .setOldController(mSimpleDraweeView.getController()) // other setters as you need .build();mSimpleDraweeView.setController(controller);
图片请求 Image Requests
Uri uri;ImageDecodeOptions decodeOptions = ImageDecodeOptions.newBuilder() .setBackgroundColor(Color.GREEN) .build();ImageRequest request = ImageRequestBuilder .newBuilderWithSource(uri) .setAutoRotateEnabled(true) .setLocalThumbnailPreviewsEnabled(true) .setLowestPermittedRequestLevel(RequestLevel.FULL_FETCH) .setProgressiveRenderingEnabled(false) .setResizeOptions(new ResizeOptions(width, height)) .build();
上面我们说了Deawee,下面我们说下Image Pipeline
配置代码
ImagePipelineConfig config = ImagePipelineConfig.newBuilder() .setBitmapMemoryCacheParamsSupplier(bitmapCacheParamsSupplier) .setCacheKeyFactory(cacheKeyFactory) .setEncodedMemoryCacheParamsSupplier(encodedCacheParamsSupplier) .setExecutorSupplier(executorSupplier) .setImageCacheStatsTracker(imageCacheStatsTracker) .setMainDiskCacheConfig(mainDiskCacheConfig) .setMemoryTrimmableRegistry(memoryTrimmableRegistry) .setNetworkFetchProducer(networkFetchProducer) .setPoolFactory(poolFactory) .setProgressiveJpegConfig(progressiveJpegConfig) .setRequestListeners(requestListeners) .setSmallImageDiskCacheConfig(smallImageDiskCacheConfig) .build();Fresco.initialize(context, config);
是在是太多了,我也懒的写了。
参考资料:中文文档
更多相关文章
- android debug set screen rotation
- Android(安卓)UI之ImageView
- android自定义ListView背景
- Android样式开发之selector
- 说说Android(安卓)两种为自定义组件添加属性的使用方法和区别
- 安卓ListView 数据分批加载
- 调用手机的摄像头,并且返回照片显示在程序界面上.
- httpClient及android 原生接口实现下载并显示图片
- android vr全景图片初探(仿微博360全景图片的实现)