Android系统Bitmap内存分配原理与优化(转)

转自:Android系统Bitmap内存分配原理与优化

一、前言

笔者最近致力于vivo游戏中心稳定性维护,在分析线上异常时,发现有相当一部分是由OutOfMemory引起。谈及OOM,我们一般都会想到内存泄漏,其实,往往还有另外一个因素——图片,如果对图片使用不当的话,很容易吃掉大量内存,从而导致异常。

尤其是游戏中心在2020末~2021初的几个重要版本,上线了很多内容相关的feature,引入大量图片、视频列表,从而导致线上OOM占比上升。

在这篇文章中,笔者将讲解一张看似普通的Bitmap对内存的占用,介绍Android Studio中帮助我们分析图片占用内存的工具,举例说明流行的两大图片加载框架:Glide、Picasso在加载图片时使用内存的不同方式,接着分析不同drawable目录下图片的显示策略,最后基于手机内存、版本,提出一种优化内存分配的方案。

二、查看图片内存占用

一张图片在内存占用的空间究竟有多少,普遍存在的一个误解是,图片本身在磁盘上/从网络下载下来是多大,就会占用多少的内存。这种说法是不正确的,图片占用内存的大小不取决于它本身的大小,而取决于图片库所采用的展示方式所申请的内存。

拿钢铁侠这张图片举例,它的尺寸是350*350,可以看到在电脑磁盘上,它只占36KB的空间。


modb_20210701_4d88f4da-da01-11eb-b2db-38f9d3cd240d.png

省略N多字。。。。。。。。

文章有点长,有兴趣的去看原文,下面只转载优化的部分:

五、优化策略

在实际的开发中,我们希望中高端机型加载更清晰的图片(ARGB_8888),以提升用户体验,对于低端机型则希望加载占用内存更小的图片(RGB_565),以降低OOM发生的概率。可以在初始化Glide时进行这样的配置。需要留意的是不要对含透明区域的图片采用这种优化方案

@GlideModule

class MyGlideModule : AppGlideModule() {


    override fun applyOptions(context: Context, builder: GlideBuilder) {

        builder.setDefaultRequestOptions(RequestOptions().format(getBitmapQuality()))

    }



    private fun getBitmapQuality(): DecodeFormat {

        return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N || hasLowRam()) {

            // 低端机型采用RGB_565以节约内存

            DecodeFormat.PREFER_RGB_565

        } else {

            DecodeFormat.PREFER_ARGB_8888

        }

    }

}

六、小结

借助一些开源工具,我们可以便捷地定位大图,如滴滴开源的DoKit,篇幅原因不进行详细介绍。最后,对于我们日常开发总结几点建议,希望大家的应用稳定性节节攀升。

  • 在多图的场景(比如RecyclerView)注意及时释放图片资源;

  • 使用占据内存更小的图片格式;

  • 图片源文件尺寸应当与目标ImageView相近;

  • 优先满足xxhdpi、xxxhdpi的图片资源需求;

  • 根据设备性能,采用不同的图片加载策略。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容