Android Fresco图片加载怎么优化

小编给大家分享一下Android Fresco图片加载怎么优化,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

优化背景

一般情况下,Fresco图片加载需使用SimpleDraweeView,这个控件并不能自动根据自身的尺寸按需加载图片,即一个 N×N 的UI控件,背后加载的实际图片可能是 2N×2N。这就导致了实际应用运行过程中的内存使用效率不高,需要针对其进行内存优化。

在一些入门级硬件设备上,表现得尤为明显,随着程序的运行时间的增长,OOM的风险也不断加大。

Fresco版本:1.13.0

数据记录

声明控件大小为 480×270

加载图片代码,调用Fresco的setImageURI

valmImageUrl="https://static.runoob.com/images/demo/demo4.jpg"
valsimple_drawee_view=findViewById(R.id.simple_drawee_view)
simple_drawee_view.setImageURI(mImageUrl)

运行后dump内存如下,可以发现内存中的图片尺寸为1920×1080,即此时SimpleDraweeView会按照网络上的原图尺寸进行加载,内存占用大小为 8294475Bytes = 7.91Mb。一张图片占用近8Mb,在图片显示十分丰富的页面场景中,图片总内存占用大小将特别美丽,万一这个页面又内存泄漏了,那就更美丽了。

如果只加载 480×270 大小的图片,内存占用为 518475Bytes = 0.49Mb。相较于原来 1920×1080 尺寸,内存减小了 94%!

优化方案

Fresco提供了resize api,使得调用者在图片解码前可以修改内存中图片的大小,api大致如下

ImageRequestrequest=ImageRequestBuilder.newBuilderWithSource(uri)
.setResizeOptions(newResizeOptions(width,height))
.build();
PipelineDraweeControllercontroller=Fresco.newDraweeControllerBuilder()
.setOldController(mDraweeView.getController())
.setImageRequest(request)
.build();
mSimpleDraweeView.setController(controller);

注意这个方案在低版本中默认只支持jpg图片,如需支持其它图片格式,需在设置image pipeline时添加isDownSample配置。同时对于产生的图片的尺寸,只能粗略地控制,图片不能修改为确定的尺寸。

.setDownsampleEnabled(true)

这个方案有个显著的缺点,那就是页面适配性极差,需要配合View层的生命周期在确保能够动态获取到控件宽高的时机进行调用,对于一个成熟的项目工程,代码改动量过大,优化成本过高。 这里采用编写SimpleDraweeView的子类进行优化,利用向上转型,尽可能的减小View层代码的改动,只需要修改xml布局文件中的控件声明即可。 方案架构图如下:

其中DesiredSimpleDraweeView为SimpleDraweeView的子类,在onWindowFocusChanged方法回调中可以明确获知控件的具体宽高,之后再进行图片加载操作。

publicclassDesiredSimpleDraweeViewextendsSimpleDraweeView{

UrimUri;
ObjectmCallerContext;

publicDesiredSimpleDraweeView(Contextcontext){
super(context);
}

@Override
publicvoidsetImageURI(Uriuri,ObjectcallerContext){
mUri=uri;
mCallerContext=callerContext;
}

privatevoidsetImageURI(intwidth,intheight){
try{
ImageRequestimageRequest=ImageRequestBuilder.newBuilderWithSource(mUri)
.setResizeOptions(newResizeOptions(width,height))
.build();
DraweeControllercontroller=
getControllerBuilder()
.setOldController(getController())
.setImageRequest(imageRequest)
.build();
setController(controller);
}catch(Exceptionex){
ex.printStackTrace();
}
}

@Override
publicvoidonWindowFocusChanged(booleanhasWindowFocus){
super.onWindowFocusChanged(hasWindowFocus);
if(hasWindowFocus){
setImageURI(getWidth(),getHeight());
}
}
}

复写setImageURI(Uri,Object)方法,暂存uri和callerContext,在onWindowFoucusChanged回调之后再根据控件宽高进行图片的加载。 这样,利用向上转型,View层的代码无需改动,xml文件中替换控件声明后即可显著提高内存利用率。

注意事项

性能优化是条永无止境的道路,没有最牛逼的方案,只有最合适的方案。如果对于图片加载尺寸想要精确控制,按需加载,Glide或许是更好的选择。

以上是“Android Fresco图片加载怎么优化”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注恰卡编程网行业资讯频道!

发布于 2021-03-17 20:53:32
分享
海报
160
上一篇:Android怎么监听屏幕旋转 下一篇:JavaScript深拷贝的注意事项
目录

    推荐阅读

    忘记密码?

    图形验证码