ImageView的scaleType设置不当,导致使用Glide时出现OOM

之前看到一篇介绍图片加载库——Glide的文章。

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0327/2650.html

看到连Google官方也在用。自动缓存,自动图片压缩,支持加载网络图片、加载Gif等等,支持集成Volley和okHttp,总之好处多多。

于是找到 Glide 在Github上面的项目主页,按照说明写了个简单的Demo。

glide

简单描述一下Demo吧,就是在tomcat上面弄一个webapp,里面就放了70来张非常大的jpg图片(某个エロゲーム 的CG,因为内容比较和谐,我就不细说了,总之每张图都有2560*1400分辨率,sample,刚好用来测试性能),还有包含着这些图片地址的json文件。

然后就是写个ListView,加载这些图片了。什么convertView复用,ViewHolder也弄好了。

运行,图片顺利加载,慢慢拖动,貌似也没问题,但是一快速滑动(也就是fling),就变得非常卡,Logcat出现 OutOfMemoryError。

OOM

检查了下程序逻辑,没啥问题,Glide的介绍提到了会按照ImageView大小了缩放和缓存图像,不至于这样啊。

百思不得其解,就去Glide项目页那里,用蹩脚的英文发了个issue,然后@TWiStErRob大神也很用心地回答了。

https://github.com/bumptech/glide/issues/464

Glad it helped. Feel free to ask further questions if you’re stuck.

For posterity: fitXY forces Glide to read at full resolution and then let the ImageView handle the distortion (fitXY doesn’t keep aspect ratio). If you want to keep distorting the images, you can keep fitXY on the imageView and call centerCrop() or fitCenter() before load(): this will make Glide downsample the image (less memory) before handing it to ImageView for distortion.

Here’s a further tip I just noticed: you could also change android:src to tools:src. That way you will save some layout passes (ImageView does a layout on every setImage*() call) and you can skip loading a bitmap (launcher icon when inflating each item) unnecessarily (you’ll overwrite it anyway with Glide). The tools attributes are not compiled into the apk, so it’s optimal to use them in these situations.

原来是ImageView的scaleType的问题,当设置为fitXY时,虽然ImageView显示那么点尺寸,但是,但是Glide加载图片时,却是以全分辨率加载的,于是加载几张,就OOM了。
改成fitCenter或者centerCrop(试了一下fitStartfitEnd也行,总之看需求了),就好了,会自动缓存小图,滚动起来也非常流畅。

完全没想到原来坑在scaleType上面,这下记住了。

最后感谢@TWiStErRob大神的耐心回答,Github已follow。