Android四大图片缓存框架之-Fresco(一)

本文介绍了Facebook的开源图片加载库Fresco,包括其强大的Image Pipeline模块,3级缓存设计,以及Drawee组件,用于高效显示和管理图片。Fresco支持多种Uri格式,并提供了丰富的XML属性和代码设置选项,允许自定义加载效果。此外,还涉及了ControllerBuilder和图片请求(Image Requests)的定制,如渐进式JPEG、Gif、多图请求等特性。
摘要由CSDN通过智能技术生成

本文来自于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,
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);

是在是太多了,我也懒的写了。

参考资料:中文文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值