前言
上图引狼
正文
在前几篇文章中已经详细的介绍了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类