Fresco正传(6):如何将PhotoView与Fresco的加载机制相结合,解决超大图显示

前言

上图引狼

正文

在前几篇文章中已经详细的介绍了Fresco。那么现在就具体应用学习到的东西,来看看PhotoView如何与Fresco相结合。

还记得DraweeView分析这篇文章吗?在其中介绍了DraweeView内部实际上是有一个DraweeHolder对象,持有了DraweeHierarchyDraweeController的引用。

在官方文档中,也实际一些DraweeHolder的用法,主要是如何利用DraweeHolder编写自定义控件,及其需要注意哪些东西。

那么也就是说,如果想要将PhotoView与Fresco结合起来,其中DraweeHolder应该是会起到关键的作用。

其次,在官方文档中提到过,如果想到自定义控件,那么保证引用计数的正确性,这样才不会内存泄露。需要特别注意下列几个方法:

 @Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    mDraweeHolder.onDetach();
}

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    mDraweeHolder.onAttach();
}

@Override
protected boolean verifyDrawable(Drawable dr) {
    super.verifyDrawable(dr);
    return dr == mDraweeHolder.getHierarchy().getTopLevelDrawable();
}

@Override
public void onStartTemporaryDetach() {
    super.onStartTemporaryDetach();
    mDraweeHolder.onDetach();
}

@Override
public void onFinishTemporaryDetach() {
    super.onFinishTemporaryDetach();
    mDraweeHolder.onAttach();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    return mDraweeHolder.onTouchEvent(event) || super.onTouchEvent(event);
}

最后,如果想要展示图片需要:

  1. 创建图片请求
  2. 获取ImagePipeline图片管道
  3. 获取数据源
  4. 获取加载数据的结果Bitmap
  5. 设置PhotoView的数据源
  6. PhotoViewDraweeHoldergetTopLevelDrawable()相结合

下面是具体代码:

/**
 * ========================================================== <br>
 * <b>版权</b>:   别志华 版权所有(c) 2015 <br>
 * <b>作者</b>:   别志华 biezhihua@163.com<br>
 * <b>创建日期</b>: 2015/11/16 17:19 <br>
 * <b>描述</b>:   <br>
 * <b>版本</b>:    V1.0 <br>
 * <b>修订历史</b>: <br>
 * 自定义的View,我们就要处理好下面这几个函数,
 * 这样才能保证引用计数的正确性,否则可能就会引起内存泄露。
 * 其实就是要在View移除屏幕或进入屏幕去维护好引用计数了。
 * onAttachedToWindow()
 * onDetacherFromWindow()
 * onStartTemporaryDetach()
 * onFinishTemporaryDetach()
 * onTouchEvent()
 * ========================================================== <br>
 */
public class MyPhotoView extends PhotoView {

    private DraweeHolder<GenericDraweeHierarchy> mDraweeHolder;

    public MyPhotoView(Context context) {
        this(context, null);
    }

    public MyPhotoView(Context context, AttributeSet attr) {
        this(context, attr, 0);
    }

    public MyPhotoView(Context context, AttributeSet attr, int defStyle) {
        super(context, attr, defStyle);
        selfInit();
    }

    private void selfInit() {
        if (mDraweeHolder == null) {
            final GenericDraweeHierarchy hierarchy = new GenericDraweeHierarchyBuilder(getResources())
                    .setProgressBarImage(new LoadingProgressDrawable(getContext())).build();

            mDraweeHolder = DraweeHolder.create(hierarchy, getContext());
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mDraweeHolder.onDetach();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        mDraweeHolder.onAttach();
    }

    @Override
    protected boolean verifyDrawable(Drawable dr) {
        super.verifyDrawable(dr);
        return dr == mDraweeHolder.getHierarchy().getTopLevelDrawable();
    }

    @Override
    public void onStartTemporaryDetach() {
        super.onStartTemporaryDetach();
        mDraweeHolder.onDetach();
    }

    @Override
    public void onFinishTemporaryDetach() {
        super.onFinishTemporaryDetach();
        mDraweeHolder.onAttach();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return mDraweeHolder.onTouchEvent(event) || super.onTouchEvent(event);
    }

    public void setImageUri(String uri, ResizeOptions options) {

        final ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(uri))
                .setResizeOptions(options)
                .setAutoRotateEnabled(true)
                .build();
        final ImagePipeline imagePipeline = Fresco.getImagePipeline();
        final DataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline.fetchDecodedImage(imageRequest, this);
        final AbstractDraweeController controller = Fresco.newDraweeControllerBuilder()
                .setOldController(mDraweeHolder.getController())
                .setImageRequest(imageRequest)
                .setControllerListener(new BaseControllerListener<ImageInfo>() {
                    @Override
                    public void onFinalImageSet(String id, ImageInfo imageInfo, Animatable animatable) {
                        super.onFinalImageSet(id, imageInfo, animatable);

                        CloseableReference<CloseableImage> imageCloseableReference = null;
                        try {
                            imageCloseableReference = dataSource.getResult();
                            if (imageCloseableReference != null) {
                                final CloseableImage image = imageCloseableReference.get();
                                if (image != null && image instanceof CloseableStaticBitmap) {
                                    CloseableStaticBitmap closeableStaticBitmap = (CloseableStaticBitmap) image;
                                    final Bitmap bitmap = closeableStaticBitmap.getUnderlyingBitmap();
                                    if (bitmap != null) {
                                        setImageBitmap(bitmap);
                    // 如果是长图,让其宽度放大至与屏幕等宽
                                        setScaleType(ScaleType.CENTER_CROP);
                                    }
                                }
                            }
                        } finally {
                            dataSource.close();
                            CloseableReference.closeSafely(imageCloseableReference);
                        }
                    }
                })
                .build();
        mDraweeHolder.setController(controller);
        setImageDrawable(mDraweeHolder.getTopLevelDrawable());
    }
}

重要问题

可能有些博友会碰到这样的问题,超级大图怎么用PhotoView显示出来呢?

这个问题开始也困扰了我很久,项目中有个400*8000的图片让我头痛的不行,但是好在最后找到了办法。请看这里

最后

是不是一点也不复杂。

还有Github例子的地址:https://github.com/biezhihua/MySimpleDraweeView

是其中的MyPhotoView类

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值