Glide 这样用,更省内存!!!

在 Glide 的这些方法内,可以看到,它们都会去操作 memoryCachebitmapPool 这两个对象,实际上它们是两个接口,这里如果做特殊处理,操作的都是 Glide 对它们的默认实现,LruResourceCacheLruBitmapPool 。从名称上可以看出来,它们都是遵循 Lru 算法的。

就 Glide 而言,Memory Cache 是 Glide 用来在内存中缓存图片资源,使其在需要使用的时候立刻就可以使用,而不必执行磁盘的 I/O 操作,而 BitmatPool 则是 Glide 维护了一个图片复用池,LruBitmapPool 使用 Lru 算法保留最近使用的尺寸的 Bitmap,这不是本文的重点,大家了解一下即可。

其实 LruResourceCache 和 LruBitmapPool 中,对 clearMemory()trimMemory() 的操作是类似的,这里就以 LruBitmapPool 举例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

/gm-LruBitmapPool.png

在 LruBitmapPool 中,会根据回调的方法以及参数,调用 clearMemory() 或者 trimToSize(),其实最终都是调用的 trimToSize() 方法。它用于裁剪当前缓存资源的个数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

/gm-trimtosize.png

可以看到,根据裁剪的目标尺寸,会去回收多余的 Bitmap 到合适的目标大小,以达到清理内存的目的。

2.2 配置 GlideModule

GlideModule 是 Glide 提供的一个配置接口,它会在第一次使用 Glide 的时候被调用,用于进行 Glide 的一些初始的配置。

具体 GlideModule 的使用,可以参见官方文档:

github.com/bumptech/gl…

GlideModule 是一个接口,需要实现其对应的方法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

/gm-module.png

这里我们只需要使用 applyOptions() 这个方法,它用于在 Glide 的默认配置的基础上,追加一些我们需要的配置。

而在这里,我们可以根据当前设备的内存情况,对其进行一个设定,使用 ActivityManager 获取当前设备的内存情况,如果是处于 lowMemory 的时候,将图片的 DecodeFormat 设置为 RGB_565RGB_565 和默认的 ARGB_8888 比,每个像素会少 2 个byte,这样,等于一张同样的图片,加载到内存中会少一半内存的占用(ARGB_8888 每个像素占 4 byte)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

/gm-apply.png

2.3 避免使用圆角的ImageView

在实际项目内,经常会用到一些带圆角的图片,或者直接就是圆形的图片。圆形的图片,多数用于一些用户的头像之类的显示效果。

而在 Android 下,也有大量的类似 XxxImageView 的开源控件,用于操作 Bitmap 以达到一个圆角图片的效果,例如 Github 上比较火的 RoundedImageView

它们大部分的原理,是接收到你传递的 Bitmap ,然后再输出一个与原来 Bitmap 等大的新 Bitmap ,在此基础之上,进行圆角的一些处理,这就导致了,实际上会在内存中,多持有一个 Bitmap ,一下一张图片占用的内存就被加倍了。

所以既然已经选择使用 Glide ,推荐使用 glide-transformations 这个开源库配合使用,glide-transformations 利用 Glide 的 bitmapTransfrom() 接口,实现对加载的 Bitmap 的进行一些变换操作。

glide-transformations 的 Github 地址如下:

github.com/wasabeef/gl…

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 ,来重新指定加载图片的尺寸。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

/gm-overr.png

既然 Glide 已经提供了标准的 Api ,那么我们还需要获取到当前运行设备的宽高。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

/gm-display.png

这里推荐使用 getRealSize() 的方式获取屏幕的宽高,它可以真实的拿到当前屏幕的尺寸。其它 Api 在部分智能电视和盒子上,拿到的尺寸会小,因为没有计算 StatusBar 或者 NavigationBar的高度,这些都是经验之谈。

同时,我们也需要用到 ComponentCallbacks2 这个接口,前面已经介绍过了,就不再赘述了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

/gm-listener.png

在其中,记录 trim 的 level 这个值,反应当前的内存级别,在使用的时候,通过 getBitmapSize() 裁剪出一个符合当前内存环境的尺寸。

例子中只是对 TRIM_MENORY_RUNNING_LOW 进行了处理,会根据屏幕尺寸,缩放到 0.8f 倍的状态。如果要做的更多,可以将其它几个 level 也加上,调整不同的缩放倍数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

/gm-fullscreenload.png

两个都输出一下,看看差别,同一张全屏的图片,不缩放和缩放 0.8f 的差别。

I/cxmyDev: bgImage byteCount : 8294400
I/cxmyDev: bgImage byteCount : 5308416
可以看到,优化的目的还是达到了。可以节约大概 3MB 左右的内存空间,而图片又不至于模糊到无法看的地步。
三、小结

优化是没有终点的,今天先聊到这里,之后有想到的再补充。如果你有什么更好的建议,可以在文末留言一起讨论一下。
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
公众号二维码.jpg
点赞或者分享吧~

总结

Android架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!

上面分享的字节跳动公司2020年的面试真题解析大全,笔者还把一线互联网企业主流面试技术要点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

就先写到这,码字不易,写的很片面不好之处敬请指出,如果觉得有参考价值的朋友也可以关注一下我

①「Android面试真题解析大全」PDF完整高清版+②「Android面试知识体系」学习思维导图压缩包阅读下载,最后觉得有帮助、有需要的朋友可以点个赞


《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
中…(img-eslmhv1Q-1714885051801)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 24
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值