Fresco的实践历程

来源:互联网 发布:下载播放软件 编辑:程序博客网 时间:2024/05/20 18:00

此文章是记录我在项目中如何使用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的原理,以及各种实现的源码,然后有机会再出一篇专门的分析文章,这次就是记录下项目中遇到的问题以及解决方案,希望可以帮助到大家。

四、用后感

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

原创粉丝点击