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()相结合

下面是具体代码:

/**
 * ========================================================== 
* 版权:   别志华 版权所有(c) 2015
* 作者:   别志华 [email protected]
* 创建日期: 2015/11/16 17:19
* 描述:   
* 版本:  V1.0
* 修订历史: 
* 自定义的View,我们就要处理好下面这几个函数, * 这样才能保证引用计数的正确性,否则可能就会引起内存泄露。 * 其实就是要在View移除屏幕或进入屏幕去维护好引用计数了。 * onAttachedToWindow() * onDetacherFromWindow() * onStartTemporaryDetach() * onFinishTemporaryDetach() * onTouchEvent() * ==========================================================
*/
public class MyPhotoView extends PhotoView { private DraweeHolder 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> dataSource = imagePipeline.fetchDecodedImage(imageRequest, this); final AbstractDraweeController controller = Fresco.newDraweeControllerBuilder() .setOldController(mDraweeHolder.getController()) .setImageRequest(imageRequest) .setControllerListener(new BaseControllerListener() { @Override public void onFinalImageSet(String id, ImageInfo imageInfo, Animatable animatable) { super.onFinalImageSet(id, imageInfo, animatable); CloseableReference 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类

你可能感兴趣的:(Android,Fresco分析)