您的位置:首页 > 其它

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

2015-11-24 15:24 330 查看

前言

上图引狼



正文

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

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

在官方文档中,也实际一些
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);
}


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

创建图片请求

获取
ImagePipeline
图片管道

获取数据源

获取加载数据的结果
Bitmap


设置
PhotoView
的数据源

PhotoView
DraweeHolder
getTopLevelDrawable()
相结合

下面是具体代码:

/**
* ========================================================== <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类
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: