Glide源码看点-图片pre scale

栏目: IOS · Android · 发布时间: 6年前

内容简介:我们都知道图片实际大小和实际显示的区域一般不能是一样的,所以如果图片尺寸本身很大但是展示区域很小的话就会,如果已完整尺寸对图片进行加载就会效率很低浪费内存,加载速度慢。所以一般我们会根据图片实际需要显示的实际大小对图片进行缩放。Android内置了inSampleSize方法来对图片进行缩放, Glide抽象出了一个类叫Downsampler.class来根据期望的图片大小和缩放策略进行向下采样。所以关键点变为了Glide如何知道我们的View实际需要的显示区域。下面将通过一个性能问题的debug故事分析

Glide是如何根据View大小对图片进行缩放优化呢 (pre scale)

我们都知道图片实际大小和实际显示的区域一般不能是一样的,所以如果图片尺寸本身很大但是展示区域很小的话就会,如果已完整尺寸对图片进行加载就会效率很低浪费内存,加载速度慢。所以一般我们会根据图片实际需要显示的实际大小对图片进行缩放。

Android内置了inSampleSize方法来对图片进行缩放, Glide抽象出了一个类叫Downsampler.class来根据期望的图片大小和缩放策略进行向下采样。所以关键点变为了Glide如何知道我们的View实际需要的显示区域。下面将通过一个性能问题的debug故事分析glide源码

Wrap Content引发的性能问题“血案”

一个类似聊天信息的界面,如果列表里有4,5张图片后,滑动就会变得异常卡顿。 Glide源码看点-图片pre scale

诊断

打开Android Monitor抓取性能Trace,发现咦咋性能消耗最大的是Glide decode Bitmap。

Glide源码看点-图片pre scale

感觉不应该啊,我图片虽然可能很大但是实际显示区域不大,Glide在显示前应该已经会根据ImageView的实际显示效果进行了缩放采样(DownSample)的优化不应该产生卡顿啊。

** 等等 ****

难道缩放采样出现了问题?

我们根据Glide的调用链找分析。


    GlideApp.with(context).load(imgUrl).into(target)

RequestBuilder的into方法其实是调用管理图片加载请求的RequestTrack里的track方法最后调用到了具体Request的begin方法。

Step1:

SingleRequest.run()方法 -> ViewTarget.getSize()

Glide源码看点-图片pre scale

如果开发者有制定大小OverrideSize就会直接采用该尺寸,如果没有就去ViewTarget里去拿size

ViewTarget.getSize -> sizeDeterminer.getSize(cb);

Glide源码看点-图片pre scale

ViewTarget里会根据SizeDeterminer去获取TargetView的具体尺寸。如果能直接从View里读取到具体的尺寸就直接用。

Glide源码看点-图片pre scale

如果读取不到就用PreDrawListener在layout完成后去监听view的实际尺寸:

observer.addOnPreDrawListener(layoutListener);

关键点来了,去看添加的preDrawListener,里面有个特殊的if语句,如果view定义了WRAP_CONTENT, Glide就无法判断到底使用什么大小去preScale图片,所以它取了屏幕的最大宽度作为图片的加载大小。(不取图片的Target.SIZE_ORIGINAL的原因是可能图片会很大,远远大于屏幕尺寸)

SizeDeterminerLayoutListener:

`

if (!view.isLayoutRequested() && paramSize == LayoutParams.WRAP_CONTENT) {
    if (Log.isLoggable(TAG, Log.INFO)) {
      Log.i(TAG, "Glide treats LayoutParams.WRAP_CONTENT as a request for an image the size of"
          + " this device's screen dimensions. If you want to load the original image and are"
          + " ok with the corresponding memory cost and OOMs (depending on the input size), use"
          + " .override(Target.SIZE_ORIGINAL). Otherwise, use LayoutParams.MATCH_PARENT, set"
          + " layout_width and layout_height to fixed dimension, or use .override() with fixed"
          + " dimensions.");
    }
return getMaxDisplayLength(view.getContext());
  }

`

元凶

看到这里刚才的性能问题迎刃而解,虽然我们界面里的ImageView实际显示区域很小(maxWitdh和maxHeight限制的),但是Glide不知道。一看我们list item的布局果然如此

Glide源码看点-图片pre scale 所以在列表里的每一张图片都是以手机的最大宽度去加载的,所以decode bitmap才花了巨大的时间。

所以Fix这个问题只需要,在加载图片前设置好需要的加载宽度就可以解决啦。

总结

图片加载的一个重要手段是,“按需显示”更具实际需要显示的图片大小进行预缩放(Pre Scale), PreScale要根据图片的显示大小和图片本身实际大小来计算inSampleSize来进行。Glide在处理Wrap Content的ImageView的时候,会不知道如何进行PreScale需要指定好具体显示的尺寸,不然可能会引发性能问题。


以上所述就是小编给大家介绍的《Glide源码看点-图片pre scale》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

程序员面试宝典

程序员面试宝典

欧立奇、刘洋、段韬 / 电子工业出版社 / 2006-7 / 39.00元

本书取材于各大IT公司历年面试真题(包括笔试题、口试题、电话面试、英语面试,以及逻辑测试和智商测试)。通过精确详细的分类,把在应聘程序员(含网络、测试等)过程中所遇见的常见考点分为21章。不仅对传统的C系语言考点做了详尽的解说,包括面向对象问题、sizeof问题、const问题、数据结构问题等。还根据外企出题最新特点,针对设计模式问题、C#问题、网络问题、数据库问题、NET问题等,做了深入的说明。......一起来看看 《程序员面试宝典》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具