Glide源码看点-图片pre scale

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

内容简介:我们都知道图片实际大小和实际显示的区域一般不能是一样的,所以如果图片尺寸本身很大但是展示区域很小的话就会,如果已完整尺寸对图片进行加载就会效率很低浪费内存,加载速度慢。所以一般我们会根据图片实际需要显示的实际大小对图片进行缩放。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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

跟小贤学运营

跟小贤学运营

陈维贤 / 机械工业出版社 / 2016-12-9 / 69.00

这是一部能帮助运营新人快速构建互联网运营方法论和快速掌握互联网运营实操的著作,是小贤在百度贴吧和小红书成长经历和运营经验的复盘。书中包含5大运营主题、40余种运营工具和渠道、50余种运营方法和技巧、100余个真实接地气的运营案例,能迅速帮助运营新人掌握全套实操技能和构建完整运营体系。 本书的视角和知识体系都比较立体化: 既有百度这样的互联网巨头运营规范和思路,又有小红书这样的明星创业公......一起来看看 《跟小贤学运营》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具