借鉴Glide思想二次封装Fresco

本篇文章已受权微信公众号 dasu_Android(大苏)独家发布java

最近封装了个 Fresco 的组件库:DFresco,就顺便来说讲。android

背景

Fresco 图片库很强大,咱们项目中就是使用的 Fresco,但有一点就是,不怎么好使用,略麻烦。不一样项目中,多多少少都须要对 Fresco 进行一层封装才能在 ui 里快速使用。git

这就致使了,不一样项目都根据本身的业务需求场景来进行封装,每次有新项目,复制粘贴时又得解决好多业务耦合的错误,麻烦,是真的麻烦~github

并且,首次接触 Fresco,接入上手的成本相比其余图片库,如 Glide,成本都要大不少。api

举个例子,假如你有这么个需求:加载一张网络上的 gif 图片,为了防止内存占用过多,须要设置分辨率压缩,最后显示到圆形控件上,同时,须要设置占位图,错误图,拉伸方式等。缓存

那么此时,你的代码可能就是这样的:微信

ImageDecodeOptions imageDecodeOptions = ImageDecodeOptions.newBuilder()
        .setDecodePreviewFrame(true).build();
ImageRequestBuilder builder = ImageRequestBuilder.newBuilderWithSource(mUri)
        .setProgressiveRenderingEnabled(true)
        .setImageDecodeOptions(imageDecodeOptions);
if (mWidth > 0 && mHeight > 0) {
    builder.setResizeOptions(new ResizeOptions(mWidth, mHeight));
}

ImageRequest request = builder.build();
AbstractDraweeController controller = Fresco.newDraweeControllerBuilder()
            .setImageRequest(request)
            .setControllerListener(listener)
            .setOldController(draweeView.getController())
            .setAutoPlayAnimations(true).build();
draweeView.setController(controller);

同时,你可能还须要在 xml 中对 SimpleDrawwView 控件进行占位图等等的配置:网络

<com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/sdv_fresco"
        android:layout_width="500dp"
        android:layout_height="500dp"
        fresco:actualImageScaleType="centerCrop"
        fresco:fadeDuration="3000"
        fresco:failureImage="@mipmap/ic_launcher"
        fresco:failureImageScaleType="centerCrop"
        fresco:placeholderImage="@mipmap/ic_launcher"
        fresco:placeholderImageScaleType="centerCrop"
        fresco:progressBarAutoRotateInterval="1000"
        fresco:progressBarImage="@drawable/ani_rotate"
        fresco:progressBarImageScaleType="centerCrop"
        fresco:retryImage="@mipmap/ic_launcher"
        fresco:retryImageScaleType="centerCrop"
        fresco:backgroundImage="@mipmap/ic_launcher"
        fresco:overlayImage="@mipmap/ic_launcher"
        fresco:pressedStateOverlayImage="@mipmap/ic_launcher"
        fresco:roundAsCircle="false"
        fresco:roundingBorderWidth="2dip"
        fresco:roundingBorderColor="@color/colorPrimary"/>

若是忘记了某个自定义属性名是什么的时候,还获得网上搜索下资料,是吧。ide

小结一下,使用 Fresco,你的接入学习成本至少须要知道 Fresco 的以下信息:学习

  • SimpleDraweeView 的自定义属性
  • ImageRequestBuilder 用法及大概用途
  • AbstractDraweeController 用法及大概用途
  • GenericDraweeHierarchy 用法及大概用途

若是涉及到一些网络下载监听,缓存之类的,那么你还要了解:

  • Imagepipeline 用法及大概用途

总之,Fresco 强大是强大,但使用起来不方便,不得不封装一层。

既然要封装,那么就直接借鉴 Glide 的使用思想来进行封装好了,若是有使用过 Glide 的应该很清楚,要实现以上功能,全程一个调用链便可。

二次封装

封装要达到的目的有两点:

  • 使用简洁、方便
  • 其余人接入直接上手的成本尽量少,最好不用去看文档,去看源码

第一点能够参考 Glide 的使用方式来设计,那么第二点个人想法是借助 AndroidStudio 的代码提示功能来实现。

好比,你只需知道,组件的入口是 DFresco 便可,其余都经过 AndroidStudio 来给你提示,如:

Dfresco入口.png

当你在 AndroidStudio 上输入 DFresco. 后,界面上会弹出你可用 api,这些就是我开放给你的入口,我将这个使用过程划分红几个步骤,每一个步骤能作什么,该作什么,我都给你规定好了,你参照着提示,直接从方法命名上就可以知道该如何使用了,AndroidStudio 会一步步引导你。

这里就两个入口,一个是用来初始化 Fresco 的:

  • init(Context)

这个内部封装了一些默认的初始化配置,好比内存大小配置,内部日志配置等等。

  • init(Context, ImagePipelineConfig)

这个是开放给你的自定义配置,若是你不想使用默认的配置的话。

  • source(String url) :加载网络上的图片
  • source(File localFile) :加载磁盘上的图片
  • source(Context context, int resId) :加载 res 内的 drawable 资源图片
  • source(Uri uri) :通用的加载方式

我将经常使用的几种图片来源单独封装出来使用,方便。

DFresco第二步.png

当调用了 source() 后就进入了第二个步骤,这个步骤中,我将图片相关的配置设计到另一个步骤中去,不然连同图片配置的 api 也都在这里的话,会搞得蛮乱的,可能让使用者到这里后不清楚该调用哪些接口了。

因此,我会把控每一个步骤的 api,尽可能让每一个步骤的 api 作的事都比较相近,好比这里:

  • intoTarget(SimpleDraweeView) 加载图片显示到控件上
  • intoTarget(SimpleDraweeView,ControllerListener) 加载图片显示到控件上,容许监听这个过程
  • intoTarget(BaseBitmapDataSubscriber) 只加载图片到内存中,以 Bitmap 形式存在

个人需求场景大概就是直接加载图片显示到控件上,或者有时候只是须要将图片加载到内存中,但不用显示到某个控件上,反而要取得图片的 Bitmap 对象,因此我将这些都封装起来了。

  • resize(int width, int height)

这个实际上就是对 Fresco 中的 ResizeOptions 的一层封装而已,简化使用,不至于像之前那么麻烦。

  • enterImageConfig()

若是你都使用默认配置的话,那么是不用再去调用那些各类配置的接口的,因此我才将图片配置封装到另一个步骤中,这个步骤你可进,可不进,若是有需求,那么经过这个方法进入图片配置步骤:

ImageConfig.png

这里的配置项不少,也是由于这个缘由,因此才不想让这些接口跟上一个步骤放一块儿,否则很容易让使用者懵掉。而进入了图片配置这个步骤后,这里提供的 api 其实就是对 GenericDraweeHierarchy 的用途进行了一层封装,或者说对 SimpleDraweeView 的自定义属性进行了一层封装。

若是你不熟悉,不要紧,其实就是一些经常使用的功能,如设置控件为圆形、圆角、边框,设置占位图、失败图、进度图、图片拉伸方式、淡入淡出动画时长等等。

这样封装的目的在于,你能够经过一条调用链的形式就设置完全部的配置,就像 Glide 的使用同样,而不用再去 new 不少 Fresco 的类,再去拼接。

进入图片配置步骤只是一个可选的步骤,进来以后固然就要出去,因此当完成了你的配置后,须要调用:finishImageConfig(),如:

第三部.png

这样就完成了图片配置,将流程切回主线了,就能够继续根据你的须要设置图片显示的目标了。

固然,为了防止再次进入图片配置步骤这样形成以前的配置项失效的场景,我借鉴了 Fresco 的 init 处理方法,即,若是一次使用过程当中,重复进入图片配置步骤,那么程序会抛异常来提醒你不能这么作。

以上,就是 DFresco 组件的封装思想,欢迎指点一下哈~

另外,参考了 Glide 的一些处理,当你的 intoTarget 是传入了 SimpleDraweeView 控件时,DFresco 内部会自动根据控件的大小对图片进行一次分辨率压缩,下降图片占用内存,固然,若是你有手动调用了 resize(),那么以你的为主。

使用示例

compile 'com.dasu.image:fresco:0.0.1'

使用以前,需先初始化,建议在 Application 中进行:

DFresco.init(this);
//加载 res 中的 drawable 图片到 SimpleDraweeView 控件上(默认支持 gif 图,而且会自动根据控件宽高进行分辨率压缩,下降内存占用
DFresco.source(mContext, R.drawable.weixin).intoTarget(mSimpleDraweeView);

//加载磁盘中的图片,手动设置分辨率的压缩,并获取 bitmap 对象,监听回调,手动显示到 ImageView 控件上
DFresco.source(new File("/mnt/sdcard/weixin.jpg"))
        .resize(500, 500)
        .intoTarget(new BaseBitmapDataSubscriber() {
                @Override
                protected void onNewResultImpl(Bitmap bitmap) {
                    Log.w("!!!!!!", "bitmap:ByteCount = " + bitmap.getByteCount() + ":::bitmap:AllocationByteCount = " + bitmap.getAllocationByteCount());
                    Log.w("!!!!!!", "width:" + bitmap.getWidth() + ":::height:" + bitmap.getHeight());
                    mImageView.setImageBitmap(bitmap);
                }

                @Override
                protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
                    Log.e("!!!!!!", "onFailureImpl");
                }
            });

//加载网络图片,进行各类配置,如缩放方式,占位图,圆形,圆角,动画时长等等,最后自动显示到 SimpleDraweeView 控件上
DFresco.source("https://upload-images.jianshu.io/upload_images/1924341-9e528ee638e837a5.png")
                    .enterImageConfig() //进入配置步骤
                    .allFitXY()  //全部图片,包括占位图等等的拉伸方式
                    .animFade(3000) //淡入淡出动画时长
                    .placeholderScaleType(ScalingUtils.ScaleType.CENTER_INSIDE) //设置占位图的拉伸方式,后面设置的会覆盖前面的
                    .actualScaleType(ScalingUtils.ScaleType.CENTER)
//                    .asRound(50) //设置圆角,(圆角和圆形不能同时设置)
                    .asCircle() //设置控件显示为圆形控件
                    .roundBorderColor(Color.RED) //设置圆角或圆形的边框颜色
                    .roundBorderWidth(20)  //设置圆角或圆形的边框宽度
                    .failure(R.drawable.timg) //设置失败图
                    .progressBar(R.drawable.aaaa) //设置加载进度图
                    .retry(R.drawable.weixin) //设置重试时的图
                    .placeholder(R.drawable.image) //设置占位图
                    .finishImageConfig() //退出配置步骤
                    .intoTarget(mSimpleDraweeView);

Github 地址

DFresco:https://github.com/woshidasusu/base-module/tree/master/fresco


你们好,我是 dasu,欢迎关注个人公众号(dasuAndroidTv),若是你以为本篇内容有帮助到你,能够转载但记得要关注,要标明原文哦,谢谢支持~
dasuAndroidTv2.png

相关文章
相关标签/搜索