美文网首页
Glide如何优化内存消耗

Glide如何优化内存消耗

作者: kevinsEegets | 来源:发表于2020-05-11 14:33 被阅读0次
1_kIIujuf1aYUVbJhJiDKiPA.png

前言

Glide是Google官方推荐的一款图片加载库,使用起来非常的简单便利,通常我们最简单的调用如下

Glide.with(this).load(imageUrl).into(image)

但是在使用Glide时候,我们可以通过一些设置来优化内存占用,避免界面出现卡顿或者OOM, 例如:一个购物网站的商品详情页有好几十张超大图(运营配置的大图一般都是高清相机直接上传的,后台也没有做图片限制),这个时候当我们上下滑动商品详情页会很明显出现卡顿,或者是我们无限制的通过猜你喜欢打开很多个商品详情页,这个时候我们通过Android Studio自带Profiler内存检测工具可以很明显的看到我们的内存很快达到极限.

我们使用最基础的方式加载一张大小为4665600 byte的图片

  Glide.with(this)
                        .load(imageUrl)
                        .skipMemoryCache(true)
                        .addListener(object : RequestListener<Drawable>{
                    override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
                        smartLog {
                            "Glide---onLoadFailed--$e"
                        }
                        return false
                    }

                    override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                        val bd =  resource as BitmapDrawable
                        val bitmap = bd.bitmap
                        result.text = "图片SIze ${bitmap.byteCount} byte"
                        smartLog {
                            "Glide---onResourceReady--图片SIze ${bitmap.byteCount} byte"
                        }
                        return false
                    }
                }).into(image)

通过logger日志看看最终我们拿到的图片大小

GlideTestActivity$onClick$1;Glide---onResourceReady--图片SIze 4665600 byte
DDDD.png

我们有哪些解决办法?

选择正确的质量(RGB)

默认情况下,色彩度为 ARGB_8888 图片,每像素会占用 4 bytes 的大小。Glide V3使用RGB_565位图格式,它需要每个像素 2 bytes ,内存占用是ARGB_8888的一半, 最新的Glide V4默认使用的是ARGB_8888格式

我们通过下图看看ARGB_8888RGB_565位图的区别

1_Vxx8-JnzenuseG7jZreoPA.png

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

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

github.com/bumptech/gl…

修改GlideV4默认配置

@GlideModule
class CustomGlideModuleV4 : AppGlideModule() {

    override fun applyOptions(context: Context, builder: GlideBuilder) {
        builder.setDefaultRequestOptions(
                RequestOptions().format(DecodeFormat.PREFER_RGB_565))
    }
}

修改Glide V3默认配置

class CustomGlideModuleV3 : GlideModule {
    fun applyOptions(context: Context, builder: GlideBuilder) {
        builder.setDecodeFormat(DecodeFormat.ALWAYS_ARGB_8888); //default in v3 is RGB_565
    }

    fun registerComponents(context: Context, glide: Glide) {
    }
}

使用RGB_565替代ARGB_8888的缺点

  • RGB_565不支持透明度,如果我们的图片不支持透明度并且节省内存的话还是可以替代的

  • RGB_565可能还存在一些别的问题, 例如图像包含渐变,你有可能会发现颜色的阴影之间会突然发生变化

  • 在Glide v3中,具有RGB_565质量的白色图像可能显示为淡黄色而不是白色。 Glide v4中没有出现此问题


    1_9FBi_-Gih0xhjsuItjvumg.png

GlideV4使用RGB_565加载大图

 Glide.with(this)
                        .load(imageUrl)
                        .skipMemoryCache(true)
                        .format(DecodeFormat.PREFER_RGB_565)
                        .addListener(object : RequestListener<Drawable>{
                    override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
                        smartLog {
                            "Glide---onLoadFailed--$e"
                        }
                        return false
                    }

                    override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                        val bd =  resource as BitmapDrawable
                        val bitmap = bd.bitmap
                        result.text = "图片SIze ${bitmap.byteCount} byte"
                        smartLog {
                            "Glide---onResourceReady--图片SIze ${bitmap.byteCount} byte"
                        }
                        return false
                    }
                }).into(image)

通过logger日志看看最终我们拿到的图片大小

GlideTestActivity$onClick$3;Glide---onResourceReady--图片SIze 2985984 byte

可以看到我们拿到的图片size比原图大小4665600 byte 少了一半

AAAA.png

图片尺寸也很重要

当然,加载的位图的大小不仅取决于其质量,还取决于大小。 在ImageView中显示图像之前,Glide调整其大小,使其适合目标尺寸,以实现最佳的内存占用。 但是,有关Glide如何工作的一些事情值得了解,没必要将大位图加载到内存中。

  Glide.with(this)
                        .load(imageUrl)
                        .skipMemoryCache(true)
                        .override(((getScreenWidth(this)*0.8).toInt()), ((getScreenHeight(this)*0.8).toInt()))
                        .addListener(object : RequestListener<Drawable>{
                    override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
                        smartLog {
                            "Glide---onLoadFailed--$e"
                        }
                        return false
                    }

                    override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                        smartLog {
                            "Glide---onResourceReady--$resource"
                        }
                        val bd =  resource as BitmapDrawable
                        val bitmap = bd.bitmap
                        result.text = "图片Size ${bitmap.byteCount} byte"
                        return false
                    }
                }).into(image)

我们通过logger日志看看最终我们拿到的图片大小

GlideTestActivity$onClick$2;Glide---onResourceReady--图片SIze 2332800 byte
BBB.png

同时调整像素RGB_565以及图片大小(原图大小的0.8倍)

Glide.with(this)
                        .load(imageUrl)
                        .skipMemoryCache(true)
                        .override(((getScreenWidth(this)*0.8).toInt()), ((getScreenHeight(this)*0.8).toInt()))
                        .format(DecodeFormat.PREFER_RGB_565)
                        .addListener(object : RequestListener<Drawable>{
                    override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
                        smartLog {
                            "Glide---onLoadFailed--$e"
                        }
                        return false
                    }

                    override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                        val bd =  resource as BitmapDrawable
                        val bitmap = bd.bitmap
                        result.text = "图片SIze ${bitmap.byteCount} byte "
                        smartLog {
                            "Glide---onResourceReady--图片SIze ${bitmap.byteCount} byte"
                        }
                        return false
                    }
                }).into(image)

我们通过logger日志看看最终我们拿到的图片大小

  GlideTestActivity$onClick$4;Glide---onResourceReady--图片SIze 1492992 byte
CCC.png

我们可以看到, 我们的原图大小为4665600,我们使用上述两种方式解决之后图片大小变为了1492992

调整完的效果还是非常棒的,美女还是那样的漂亮,只有后边背景颜色有些许的减淡,但是我们大幅度降低图片内存占用,为了我们手机性能的大幅度提高这点质量上的损失还是可以接受的(除非UI设计师太苛刻).

Glide是一个很棒的库,可以轻松加载图像。 但是,有时候最好知道它如何以最有效的内存方式使用。 我希望我在本文中描述的事实将帮助您减少应用程序的内存占用,并避免一些邪恶的OOM错误。

参考文章
https://proandroiddev.com/how-to-optimize-memory-consumption-when-using-glide-9ac984cfe70f

相关文章

  • Glide如何优化内存消耗

    前言 Glide是Google官方推荐的一款图片加载库,使用起来非常的简单便利,通常我们最简单的调用如下 但是在使...

  • 第8章 理解内存

    理解Redis内存消耗,管理和优化。 1. 内存消耗 1.1 内存使用统计 通过info memory命令获取内存...

  • Glide源码解析

    问题 glide是如何进行缓存的? glide是如何多线程加载图片? glide如何进行内存管理? 为何要选择gl...

  • Redis实践(十六)-内存管理

    1 内存优化介绍 2 Redis内存消耗 3 客户端缓冲区

  • 面试

    Android 面试要点 2.13更新 内存优化 什么是oom,如何避免? 如何内存控制,内存优化内存泄漏会导致内...

  • Redis内存优化

    Redis内存优化 1.内存消耗 1.1内存使用统计 属性名属性说明used_memoryRedis 分配器分配的...

  • Glide的图片内存优化

    首先,内存总量有限,必须限制图片加载的内存 弱引用 这个大家都懂,好多第三方加载组件也体现了这个思路。 最早,大家...

  • Glide(图片加载)

    Glide Glide使用文档 Glide 系列教程 玩转Glide的Target对象 Glide-内存缓存与磁盘...

  • Glide 相关文集 面试 及 源码 持续更新 1.0.0

    Glide的优点 使用简单 链式调用 占用内存较小 无代码侵入 支持GIF 缓存优化 与Activity生命周期绑...

  • 2. 托管内存

    对于Unity内存管理而言,需要理解托管堆。对于如何分析托管内存和如何优化内存,可以参见Unity优化中的理解托管...

网友评论

      本文标题:Glide如何优化内存消耗

      本文链接:https://www.haomeiwen.com/subject/ypeunhtx.html