Fresco的实践历程

此文章是记录我在项目中如何使用Fresco,以及遇到的问题,还有相对应的解决方案。

1.添加防盗链;

2.直接下载图片,不需要控件去调用;

3.如何实现既要求可以从相册选取,又可以直接网络下载的圆角图片;


一、Fresco集成以及使用方法的中文官网地址:点击打开链接

二、正常的操作流程我就不再赘述,我接下来主要介绍我们项目中遇到的问题。     

1、由于我们公司对于图片安全要求比较严格,需要加防盗链,所以介绍Fresco添加防盗链的方法如下:

  public static void initFresco(Context context) {
        ImagePipelineConfig config = OkHttpImagePipelineConfigFactory
                .newBuilder(context, getOkHttpClientForFresco()).build();
        Fresco.initialize(context, config);
    }

    private static OkHttpClient getOkHttpClientForFresco() {
        OkHttpClient client;
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .addInterceptor(new HeaderInterceptor())
                .connectTimeout(20, TimeUnit.SECONDS);
        client = builder.build();
        return client;
    }

    private static class HeaderInterceptor implements Interceptor {
        private HashMap<String, String> mHeadMap;

        private HeaderInterceptor() {
            mHeadMap = new HashMap<>();
        }

        @Override
        public Response intercept(Chain chain) throws IOException, BaseException {
            Request request = chain.request();
            Request.Builder builder = request.newBuilder();
            for (String s : mHeadMap.keySet()) {
                builder.addHeader(s, mHeadMap.get(s));
            }
            builder.addHeader("Referer", "xxxx");
            builder.addHeader("Cookie", "xxx");
            request = builder.build();
            return chain.proceed(request);
        }
    }

2、由于之前我们用到的图片有圆角的,虽然Fresco官网提供了设置圆角的方法,但是这只是限于调用下载api的时候,我们所用到的场景是有时候需要从拍照获取,有时候需要从网络下载,所以这个设置圆角的api并不能满足所有的场景,于是我就将从拍照获取的Bitmap进行剪裁,剪裁成圆角图片,代码如下:

  public static Bitmap getRoundRectBitmap(Bitmap bitmap, int radius) {
        Bitmap target = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), ARGB_8888);
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);

        int bmWidth = target.getWidth();
        int bmHeight = target.getHeight();
        final Rect rect = new Rect(0, 0, bmWidth, bmHeight);
        final RectF rectF = new RectF(0, 0, bmWidth, bmHeight);

        Canvas canvas = new Canvas(target);

        paint.setXfermode(null);
        canvas.drawRoundRect(rectF, radius, radius, paint);
        paint.setXfermode(new PorterDuffXfermode(SRC_IN));
        canvas.drawBitmap(bitmap, rect, rectF, paint);

        return target;
    }

3、Fresco是没有一个单独的api直接用于图片下载,而不需要控件调用的,需要自己去实现,解决办法如下:(ps:其中onGetFrescoImgListener是自己定义的一个interface,大家可以自行去修改)

 /**
     * 根据url下载图片,返回字节数组
     */
    public static void frescoDownloadImg(@NonNull String url, @NonNull Activity context, @Nullable OnGetFrescoImgListener listener) {
        Uri uri = Uri.parse(url);
        ImagePipeline imagePipeline = Fresco.getImagePipeline();
        ImageRequestBuilder builder = ImageRequestBuilder.newBuilderWithSource(uri);
        ImageRequest imageRequest = builder.build();

        // 获取未解码的图片数据
        DataSource<CloseableReference<PooledByteBuffer>> dataSource = imagePipeline.fetchEncodedImage(imageRequest, context);

        dataSource.subscribe(new BaseDataSubscriber<CloseableReference<PooledByteBuffer>>() {
            private byte[][] data = new byte[1][1];

            @Override
            public void onNewResultImpl(DataSource<CloseableReference<PooledByteBuffer>> dataSource) {
                if (!dataSource.isFinished()) {
                    return;
                }

                CloseableReference<PooledByteBuffer> imageReference = dataSource.getResult();
                if (imageReference != null) {
                    final CloseableReference<PooledByteBuffer> closeableReference = imageReference.clone();
                    try {
                        PooledByteBuffer pooledByteBuffer = closeableReference.get();
                        InputStream inputStream = new PooledByteBufferInputStream(pooledByteBuffer);
                        data[0] = input2byte(inputStream);
                        context.runOnUiThread(new Thread(() -> {
                            if (listener != null) {
                                listener.getFrescoImgByteSuccess(data[0]);
                            }
                        }));
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        closeableReference.close();
                    }
                }
            }

            @Override
            public void onFailureImpl(DataSource dataSource) {
                context.runOnUiThread(new Thread(() -> {
                    if (listener != null) {
                        listener.getFrescoImgByteFail(data[0]);
                    }
                }));
            }
        }, Executors.newSingleThreadExecutor());
    }
  public interface OnGetFrescoImgListener {

        void getFrescoImgByteSuccess(byte[] data);

        void getFrescoImgByteFail(byte[] data);
    }

使用方法如下:

    /**
     * Fresco直接通过Url下载图片获取字节数组(异步)
     */
    private void getBitmapFromUrl(String title, String link, String desc, String url, int flag) {

        FrescoUtil.frescoDownloadImg(url, (Activity) mContext, new FrescoUtil.OnGetFrescoImgListener() {
            @Override
            public void getFrescoImgByteSuccess(byte[] data) {
                startShareWechat(title, link, desc, data, flag);
            }

            @Override
            public void getFrescoImgByteFail(byte[] data) {
                startShareWechat(title, link, desc, data, flag);
            }
        });
    }

4、接下来我贴一下我自己封装的FrescoUtil,还是个不怎么成熟的程序员,希望大家多多提建议,多多指教,接受批评和指正。

public class FrescoUtil {

    public static void initFresco(Context context) {
        ImagePipelineConfig config = OkHttpImagePipelineConfigFactory
                .newBuilder(context, getOkHttpClientForFresco()).build();
        Fresco.initialize(context, config);
    }

    private static OkHttpClient getOkHttpClientForFresco() {
        OkHttpClient client;
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .addInterceptor(new HeaderInterceptor())
                .connectTimeout(20, TimeUnit.SECONDS);
        client = builder.build();
        return client;
    }

    private static class HeaderInterceptor implements Interceptor {
        private HashMap<String, String> mHeadMap;

        private HeaderInterceptor() {
            mHeadMap = new HashMap<>();
        }

        @Override
        public Response intercept(Chain chain) throws IOException, BaseException {
            Request request = chain.request();
            Request.Builder builder = request.newBuilder();
            for (String s : mHeadMap.keySet()) {
                builder.addHeader(s, mHeadMap.get(s));
            }
            builder.addHeader("Referer", "xxx");
            builder.addHeader("Cookie", "xxx");
            request = builder.build();
            return chain.proceed(request);
        }
    }

   public interface OnGetFrescoImgListener {

        void getFrescoImgByteSuccess(byte[] data);

        void getFrescoImgByteFail(byte[] data);
    }

    /**
     * SimpleDraweeView 加载 url
     */
    public static void frescoSetImg(@NonNull SimpleDraweeView iv,
                                    String url) {
        iv.setImageURI(url);
    }

    /**
     * SimpleDraweeView 设置 GenericDraweeHierarchy 加载 url
     */
    public static void frescoSetImg(@NonNull SimpleDraweeView iv,
                                    @NonNull GenericDraweeHierarchy hierarchy,
                                    String url) {
        iv.setHierarchy(hierarchy);
        iv.setImageURI(url);
    }

    /**
     * GenericDraweeHierarchy 设置 占位图、失败图,SimpleDraweeView 设置 GenericDraweeHierarchy 加载 url
     */
    public static void frescoSetImg(@NonNull SimpleDraweeView iv,
                                    String url,
                                    int placeholderImageResId,
                                    int failureImageResId,
                                    @NonNull Context context) {
        frescoSetRoundImg(iv, url, placeholderImageResId, failureImageResId, null, null, context, null);
    }

    /**
     * GenericDraweeHierarchy 设置 占位图、占位图的何种比例缩放(可以传null)、失败图、失败图的何种比例缩放(可以传null),SimpleDraweeView 设置
     * GenericDraweeHierarchy 加载 url
     */
    public static void frescoSetImg(@NonNull SimpleDraweeView iv,
                                    String url,
                                    int placeholderImageResId,
                                    int failureImageResId,
                                    @Nullable ScalingUtils.ScaleType placeholderScale,
                                    @Nullable ScalingUtils.ScaleType failureImageScaleType,
                                    @NonNull Context context) {
        frescoSetRoundImg(iv, url, placeholderImageResId, failureImageResId, placeholderScale, failureImageScaleType, context, null);
    }

    /**
     * GenericDraweeHierarchy 设置 占位图、失败图,SimpleDraweeView 设置 GenericDraweeHierarchy 加载 url
     */
    public static void frescoSetImg(
            @NonNull SimpleDraweeView iv,
            String url,
            int placeholderImageResId,
            int failureImageResId,
            @Nullable RoundingParams roundingParams,
            @NonNull Context context) {

        frescoSetRoundImg(iv, url, placeholderImageResId, failureImageResId, null, null, context, roundingParams);
    }

    /**
     * GenericDraweeHierarchy 设置 占位图、占位图的何种比例缩放、失败图、失败图的何种比例缩放、圆角设置,SimpleDraweeView 设置
     * GenericDraweeHierarchy 加载 url
     */
    public static void frescoSetRoundImg(@NonNull SimpleDraweeView iv,
                                         String url,
                                         int placeholderImageResId,
                                         int failureImageResId,
                                         @Nullable ScalingUtils.ScaleType placeholderScale,
                                         @Nullable ScalingUtils.ScaleType failureImageScaleType,
                                         @NonNull Context context,
                                         @Nullable RoundingParams roundingParams) {
        GenericDraweeHierarchy genericDraweeHierarchy = GenericDraweeHierarchyBuilder.newInstance(context.getResources())
                .setPlaceholderImage(placeholderImageResId)
                .setFailureImage(failureImageResId)
                .setRoundingParams(roundingParams)
                .setPlaceholderImageScaleType(placeholderScale)
                .setFailureImageScaleType(failureImageScaleType)
                .build();
        iv.setHierarchy(genericDraweeHierarchy);
        iv.setImageURI(url);
    }

    /**
     * 根据url下载图片,返回字节数组
     */
    public static void frescoDownloadImg(@NonNull String url, @NonNull Activity context, @Nullable OnGetFrescoImgListener listener) {
        Uri uri = Uri.parse(url);
        ImagePipeline imagePipeline = Fresco.getImagePipeline();
        ImageRequestBuilder builder = ImageRequestBuilder.newBuilderWithSource(uri);
        ImageRequest imageRequest = builder.build();

        // 获取未解码的图片数据
        DataSource<CloseableReference<PooledByteBuffer>> dataSource = imagePipeline.fetchEncodedImage(imageRequest, context);

        dataSource.subscribe(new BaseDataSubscriber<CloseableReference<PooledByteBuffer>>() {
            private byte[][] data = new byte[1][1];

            @Override
            public void onNewResultImpl(DataSource<CloseableReference<PooledByteBuffer>> dataSource) {
                if (!dataSource.isFinished()) {
                    return;
                }

                CloseableReference<PooledByteBuffer> imageReference = dataSource.getResult();
                if (imageReference != null) {
                    final CloseableReference<PooledByteBuffer> closeableReference = imageReference.clone();
                    try {
                        PooledByteBuffer pooledByteBuffer = closeableReference.get();
                        InputStream inputStream = new PooledByteBufferInputStream(pooledByteBuffer);
                        data[0] = input2byte(inputStream);
                        context.runOnUiThread(new Thread(() -> {
                            if (listener != null) {
                                listener.getFrescoImgByteSuccess(data[0]);
                            }
                        }));
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        closeableReference.close();
                    }
                }
            }

            @Override
            public void onFailureImpl(DataSource dataSource) {
                context.runOnUiThread(new Thread(() -> {
                    if (listener != null) {
                        listener.getFrescoImgByteFail(data[0]);
                    }
                }));
            }
        }, Executors.newSingleThreadExecutor());
    }

三、总结

虽然花费了一个星期的时间去替换了项目的图片第三方加载库,但是也只是限于解决了问题,我还是有点不求甚解,这种感觉很不好,我会在接下来的时间去认真的研究下这个Fresco的原理,以及各种实现的源码,然后有机会再出一篇专门的分析文章,这次就是记录下项目中遇到的问题以及解决方案,希望可以帮助到大家。

四、用后感

其实用起来感觉没有这么方便,各种方法封装的不够,但是换句话说,灵活性比较高,可以自己去搞,也有一方面是自己能力不足,希望以后自己越来越好。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值