Glide 这样用,更省内存!!! 1
一、前言
Glide 是 Google 官方推荐的一款图片加载库,使用起来也非常的简单便利,Glide 它帮我们完成了很多很重要,但是却通用的功能,例如:图片的加载压缩、展示、加载图片的内存管理等等。
对 Glide 还不熟悉的朋友,可以参考 《一篇好文,助你上手 Glide》
但是,在使用 Glide 的时候,有一些小技巧,可以让你的内存更优化,避免可能出现的 OOM。例如:虽然 Glide 会根据加载的控件大小,优化加载后的图片尺寸,可如果加载的是一张全屏的大图,依然会是一个占用内存空间非常大的操作。
具体一张 Bitmap 到底占用了多少内存空间,可以参考《Bitmap 比你想的更费内存 | 吊打 OOM》
本文有些建议来自 Android TV App,而 Android TV 众多的智能电视和智能盒子,实际上硬件条件非常的恶劣,而 Android TV 的 App ,为了美化,会用到大部分的图片,所以在图片使用方面,OOM 的问题就会被放大,而下面介绍的一些优化方案,在 Android 手机硬件条件非常好的环境下,不使用影响也不大。
二、开始优化
2.1 配置好 TrimMemory 和 LowMemory
Glide 帮我们做了大部分内存管理方面的事情,实际上它还支持做的更好。
对于一个 App 而言,在系统内存环境不足的情况下,会回调一些 onTrimMemory()
或者 onLowMemory()
等方法,这些都是在提醒开发者,当前设备的内存环境已经发生了变化,你最好调整你的内存使用策略,避免被系统清理掉或者出现 OOM 。
关于 onTrimMemroy()
相关内容,不了解的可以先参考《Android 开发,跳不过的内存管理》
而 Glide 也为我们提供了类似方法的接口,开发者只需要调用即可,它在内部会随着不同的内存情况,帮我们对缓存的图片进行优化。
在这里,你主要用到 Glide 的 trimMemory()
和 cleanMemroy()
方法,它们一个用来裁剪 Glide 缓存的图片内存空间,一个用来清理 Glide 缓存的内存空间。
在使用 onTrimMemory()
之前,一般是实现 ComponentCallbacks2 接口,然后在 Application 中,通过 registerComponentCallbacks()
方法进行注册。当然,如果你嫌麻烦,还可以直接在 Application 中,重写对应的方法。
了解了这些,就可以根据我们的需要来配置在何时调用 Glide 的对应方法,我推荐的配置:
- 在 lowMemory 的时候,调用
Glide.cleanMemroy()
清理掉所有的内存缓存。 - 在 App 被置换到后台的时候,调用
Glide.cleanMemroy()
清理掉所有的内存缓存。 - 在其它情况的
onTrimMemroy()
回调中,直接调用Glide.trimMemory()
方法来交给 Glide 处理内存情况。
那么对应的代码,如下:
既然知道需要调用 Glide 的这两个方法,我们还是需要了解到它内部到底帮我们做了什么。先来看看 Glide 对应的源码。
在 Glide 的这些方法内,可以看到,它们都会去操作 memoryCache 和 bitmapPool 这两个对象,实际上它们是两个接口,这里如果做特殊处理,操作的都是 Glide 对它们的默认实现,LruResourceCache 和 LruBitmapPool 。从名称上可以看出来,它们都是遵循 Lru 算法的。
就 Glide 而言,Memory Cache 是 Glide 用来在内存中缓存图片资源,使其在需要使用的时候立刻就可以使用,而不必执行磁盘的 I/O 操作,而 BitmatPool 则是 Glide 维护了一个图片复用池,LruBitmapPool 使用 Lru 算法保留最近使用的尺寸的 Bitmap,这不是本文的重点,大家了解一下即可。
其实 LruResourceCache 和 LruBitmapPool 中,对 clearMemory()
和 trimMemory()
的操作是类似的,这里就以 LruBitmapPool 举例。
在 LruBitmapPool 中,会根据回调的方法以及参数,调用 clearMemory()
或者 trimToSize()
,其实最终都是调用的 trimToSize()
方法。它用于裁剪当前缓存资源的个数。
可以看到,根据裁剪的目标尺寸,会去回收多余的 Bitmap 到合适的目标大小,以达到清理内存的目的。
2.2 配置 GlideModule
GlideModule 是 Glide 提供的一个配置接口,它会在第一次使用 Glide 的时候被调用,用于进行 Glide 的一些初始的配置。
具体 GlideModule 的使用,可以参见官方文档:
https://github.com/bumptech/g...
GlideModule 是一个接口,需要实现其对应的方法。
这里我们只需要使用 applyOptions()
这个方法,它用于在 Glide 的默认配置的基础上,追加一些我们需要的配置。
而在这里,我们可以根据当前设备的内存情况,对其进行一个设定,使用 ActivityManager 获取当前设备的内存情况,如果是处于 lowMemory 的时候,将图片的 DecodeFormat 设置为 RGB_565 , RGB_565 和默认的 ARGB_8888 比,每个像素会少 2 个byte,这样,等于一张同样的图片,加载到内存中会少一半内存的占用(ARGB_8888 每个像素占 4 byte)。
2.3 避免使用圆角的ImageView
在实际项目内,经常会用到一些带圆角的图片,或者直接就是圆形的图片。圆形的图片,多数用于一些用户的头像之类的显示效果。
而在 Android 下,也有大量的类似 XxxImageView 的开源控件,用于操作 Bitmap 以达到一个圆角图片的效果,例如 Github 上比较火的 RoundedImageView。
它们大部分的原理,是接收到你传递的 Bitmap ,然后再输出一个与原来 Bitmap 等大的新 Bitmap ,在此基础之上,进行圆角的一些处理,这就导致了,实际上会在内存中,多持有一个 Bitmap ,一下一张图片占用的内存就被加倍了。
所以既然已经选择使用 Glide ,推荐使用 glide-transformations 这个开源库配合使用,glide-transformations 利用 Glide 的 bitmapTransfrom()
接口,实现对加载的 Bitmap 的进行一些变换操作。
glide-transformations 的 Github 地址如下:
https://github.com/wasabeef/g...
glide-transformations 提供一系类对加载的图片的变换操作,从形状变换到色彩变换,全部支持,基本上满足大部分开发需要,并且它会复用 Glide 的 BitmapPool ,来达到节约内存的目的。
具体 glide-transformations 的使用,可以查看 Github 上的文档,下面是它的一个效果图。
2.4 根据内存情况,裁剪你的图片
前面的介绍的一些优化点,都是一些推荐的通用做法,基本上用了前面介绍的办法,图片导致的 OOM 应该会大幅度减少。
接下来介绍一个在 Android TV 上,加载全屏大图的时候,优化内存问题的一个解决办法。
首先要明确一点,国内 Android TV 的硬件环境非常的不好,二百三百的智能盒子到处都在卖,毕竟也是跑的 Android 系统,你想想你使用的是一款 299 的 Android 手机,你对它也不会有什么期待了。但是 Android TV 又是为了电视做的,所以大部分情况下,它都是需要支持 1920 * 1280 之类的屏幕尺寸,导致它如果加载一张全屏的大图,消耗的内存是不忍直视的,如果在内存环境不好的情况下,可能就直接 OOM 崩溃了。
所以,对于这种极端的情况,我想到了一个办法,根据当前的内存环境,按比例缩小需要显示的全屏图片,这样加载到内存中的图片,就是按比例缩小的。
在这里就需要用到 DrawableRequestBuilder 的 override()
这个 Api 了,它可以接受一个 width 和 height ,来重新指定加载图片的尺寸。
既然 Glide 已经提供了标准的 Api ,那么我们还需要获取到当前运行设备的宽高。
这里推荐使用 getRealSize()
的方式获取屏幕的宽高,它可以真实的拿到当前屏幕的尺寸。其它 Api 在部分智能电视和盒子上,拿到的尺寸会小,因为没有计算 StatusBar 或者 NavigationBar的高度,这些都是经验之谈。
同时,我们也需要用到 ComponentCallbacks2 这个接口,前面已经介绍过了,就不再赘述了。
在其中,记录 trim 的 level 这个值,反应当前的内存级别,在使用的时候,通过 getBitmapSize()
裁剪出一个符合当前内存环境的尺寸。
例子中只是对 TRIM_MENORY_RUNNING_LOW 进行了处理,会根据屏幕尺寸,缩放到 0.8f 倍的状态。如果要做的更多,可以将其它几个 level 也加上,调整不同的缩放倍数。
两个都输出一下,看看差别,同一张全屏的图片,不缩放和缩放 0.8f 的差别。
I/cxmyDev: bgImage byteCount : 8294400
I/cxmyDev: bgImage byteCount : 5308416
可以看到,优化的目的还是达到了。可以节约大概 3MB 左右的内存空间,而图片又不至于模糊到无法看的地步。
三、小结
优化是没有终点的,今天先聊到这里,之后有想到的再补充。如果你有什么更好的建议,可以在文末留言一起讨论一下。
点赞或者分享吧~
Glide 这样用,更省内存!!! 1相关推荐
- Glide 这样用,更省内存
本文讲的是Glide 这样用,更省内存, 一.前言 Glide 是 Google 官方推荐的一款图片加载库,使用起来也非常的简单便利,Glide 它帮我们完成了很多很重要,但是却通用的功能,例如:图片 ...
- Glide 这样用,更省内存!!!
一.前言 Glide 是 Google 官方推荐的一款图片加载库,使用起来也非常的简单便利,Glide 它帮我们完成了很多很重要,但是却通用的功能,例如:图片的加载压缩.展示.加载图片的内存管理等等. ...
- MVVM更容易内存泄露吗?
由于MVVM是把View, ViewModel, Model紧紧绑定在一起的模式,特别视图和视图模型通过实现观察者模式双向绑定和NotifyPropertyChanged事件,似乎更加容易造成内存泄露 ...
- 更多核心、更大内存、更低成本 AMD皓龙6000欲成云计算基石
随着AMD携手盛大 "龙起云涌 芯聚多核――AMD皓龙6000系列平台发布会暨盛大AMD云计算联合实验室启动联合发布会"的召开,为业界带来最高可达4路48核的x86服务器系统的同时 ...
- 1034 Head of a Gang(7ms,并查集版,比图的版本快得多,更省内存
9ms,并查集版,比图的版本快得多,更更更省内存 题目 题意: 给出1000条以内的通话记录A B和权值w,和阈值k,如果一个团伙人数超过2人并且通话总权值超过k,令团伙里面的自身权值的最大值为头目, ...
- pycharm运行模型时怎么设置权重?_使用AMP和Tensor Cores得到更快速,更节省内存的PyTorch模型...
点击上方"AI派",关注公众号,选择加"星标"或"置顶" 导读 只需要添加几行代码,就可以得到更快速,更省显存的PyTorch模型. 你知道 ...
- 比 Redis 还快,更省内存,惊爆了!
点击关注公众号:互联网架构师,后台回复 2T获取2TB学习资源! 上一篇:Alibaba开源内网高并发编程手册.pdf 最近,一位前谷歌.前亚马逊的工程师推出了他创作的开源内存数据缓存系统 Drago ...
- 比 Redis 还快,更省内存,开源,惊爆了!
今年年中,一位前谷歌.前亚马逊的工程师推出了他创作的开源内存数据缓存系统 Dragonfly,用 C/C++ 编写,基于 BSL 许可(Business Source License)分发. 根据过往 ...
- Glide清除缓存(清除内存缓存、本地缓存、清除所有缓存等)
Glide使用讲解 https://blog.csdn.net/bzlj2912009596/article/details/81702367 Glide的图片缓存在/data/data/项目包名/c ...
最新文章
- 机器人c语言教程pdf,机器人卡雷尔学习C语言.pdf
- Stucts应用引起的OutOfMemoryError
- Spring MVC 完整示例
- 树莓派命令连接wifi_树莓派连接无线网wifi配置方法
- initialization of 'XXX' is skipped by 'case' label
- 有道智能学习灯 初体验
- 华三防火墙h3cf100配置双宽带_H3C新一代F100系列防火墙评测报告
- docker 导出堆栈信息.hprof_JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof使用...
- MAC下的环境变量配置
- iconfont-阿里巴巴矢量图标库的使用方法
- 关于apipost接口测试
- 2022年化肥行业发展趋势
- web期末网站设计大作业 HTML+CSS+JS仿爱奇艺官网影视网站
- MPC与LQR的详细对比分析
- java支付宝app支付代码
- 行走在数据库上的行癫(一)
- cross_val_score中scoring参数
- 一小时刷完英语口语常用3000词汇(绿色护眼版)day6-词汇501-600
- javascript打印直角三角形四种情况
- 如何快速绘制电气原理图,回路图