Glide内存占用优化

近期项目中选用glide作为图片加载工具,布局采用NestedScrollView嵌套RecyclerView实现,recycleview中的条目有张图片,通过glide添加,RecyclerView不断下滑不断加载更多item,随着recycleview中的item数量的不断增加,应用内存不断增长直至最后OOM退出

查找发现内存暴涨是因为recyvleview中的item条目数量太多,每个条目都持有一个bitmap占用了大量内存,要想内存保持不暴涨,必须做到及时回收item中的bitmap,在adapter中重写item回收方法:

    @Override
    public void onViewRecycled(@NonNull BaseViewHolder holder) {
        MyLog.e(TAG,"onViewRecycled");
        ImageView imageView = holder.itemView.findViewById(R.id.goods_img);
        if(imageView!=null) {
            imageView.setImageDrawable(null);
            Glide.with(imageView.getContext()).clear(imageView);
        super.onViewRecycled(holder);

发现onViewRecycled有调用,但是调用的次数非常少,相对于大量的添加item来说,这点回收无济于事,通过网络查找发现NestedScrollView+RecyclerView的使用方式会导致RecyclerView不复用item,所以修改代码结构,将NestedScrollView+Recycleview的形式改为单独recycleview,之前在NestedScrollView中的其他子view添加到recycleview中,添加方法类似添加header、footer,这样RecyclerView的复用功能就能正常使用,修改后发现onViewRecycled方法调用非常频繁,内存很好的控住住了,没有出现暴涨。

随后继续针对glide添加优化,使用glide提供的全局设置进步一降低缓存池大小和图片质量,glide全局配置使用如下:
添加module类:

public class CouponModule implements GlideModule {
    private static final String TAG = "CouponModule";
    @Override
    public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
        MemorySizeCalculator calculator = new MemorySizeCalculator.Builder(CouponApplication.getContext()).build();
        int defaultMemoryCacheSize = calculator.getMemoryCacheSize();
        int defaultBitmapPoolSize = calculator.getBitmapPoolSize();
        int defaultArrayPoolSize = calculator.getArrayPoolSizeInBytes();
        builder.setDefaultRequestOptions(
                new RequestOptions()
                        .format(DecodeFormat.PREFER_RGB_565));
        builder.setMemoryCache(new LruResourceCache(defaultMemoryCacheSize/2));
        builder.setBitmapPool(new LruBitmapPool(defaultBitmapPoolSize/2));
        builder.setArrayPool(new LruArrayPool(defaultArrayPoolSize/2));
    @Override
    public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {

manifest文件添加meta-data信息:

<meta-data android:name="com.android.**.CouponModule"
            android:value="GlideModule"/>

混淆脚本修改:

#glide module混淆
#-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class com.android.hshq.coupon.CouponModule
# for DexGuard only
#-keepresourcexmlelements manifest/application/meta-data@value=GlideModule

更多内容查看wiki:https://github.com/bumptech/glide/wiki/Configuration

在全局设置中将图片质量设置为565,如果遇到显示gif文件的时候,会出现gif图片周边出现黑框的问题,需要在加载图片时候,单独针对gif结尾的url将图片质量改回8888

public static void display(Context context, String url, ImageView imageView) {
        RequestOptions options = new RequestOptions()
                .centerCrop()
                .placeholder(R.drawable.ic_refresh_loading)
                .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
                .error(R.drawable.ic_refresh_bad_net);
        if(!TextUtils.isEmpty(url) && url.endsWith(".gif")) {
            options.format(DecodeFormat.PREFER_ARGB_8888);
        Glide.with(context)
                .load(url)
                .apply(options)
                .into(imageView);

glide总体来说使用非常方便,不需要从布局层面开始修改,gif图片自动播放,但是在内存回收方面不及fresco,fresco会在图片不可见的情况下主动回收内存,中途本也考虑过将glide替换为fresco,但最终测试结果发现添加主动回收操作以及限制图片质量后占用内存与使用fresco的情况下差不多,就没有替换为fresco。
在以后遇到巨量图片加载任务的项目中,我想我会首选使用fresco作为图片加载工具使用。

RecyclerView 滑动时的优化处理,在滑动时停止加载图片,在滑动停止时开始加载图片,这里用了Glide.pause 和Glide.resume.这里为了避免重复设置增加开销,设置了一个标志变量来做判断。 mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recycl 本项目是基于Luban算法,重构后实现的图片压缩框架 KLuban 使用Kotlin + 协程 + Flow(并行任务) + LiveData(监听回调) + Glide图片识别和内存优化 + 邻近(鲁班)、双线性采样图片算法压缩框架,欢迎改进 fork 和 star 集成和使用 Step 1.Add it in your root build.gradle at the end of repositories: allprojects { repositories { maven { url 'https://jitpack.io' } Step 2.Add the dependency dependencies { implementation 'com.github.forJrking:KLuban:1.0.7' Step 3.Ap 该系列的上两篇介绍了如何高效地量化绘制性能,并对 RecyclerView 加载速度做了 4 次优化,使得表项加载耗时从 370 ms 缩减到 170 ms。这一篇再介绍一种... recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { 前言最近在项目中使用了一个GitHub上开源的图片选择器库,在android8.0以上的机子测试没发现异常,正常将相册里的相片加载到Recyclerview,但测试了美图一台Android7.1的手机却出现了闪退,看日志发现是OutOfMemory。首先想到的是Glide的使用是不是不太正确,于是有了以下尝试:尝试1:Glide的diskCacheStrategy属性Glide.with(mCon... Glide 是 Google 官方推荐的一款图片加载库,使用起来也非常的简单便利,Glide 它帮我们完成了很多很重要,但是却通用的功能,例如:图片的加载压缩、展示、加载图片的内存管理等等。 对 Glide 还不熟悉的朋友,可以参考 《一篇好文,助你上手 Glide》 但是,在使用 Glide 的时候,有一些小技巧,可以让你的内存优化,避免可能出现的 OOM。例如 1.图片缓存增多:采用图片加载栈缓存清除+预加载方案,实测效果并不理想,非本质问题 2.图片缩放处理:调用override() 方法,对图片进行压缩,实测确实有效果,单还会有卡顿现象,增大压缩率后,卡顿现象确实有很大的优化,但是伴随的却是列表中的图片非常模糊..... 3.图片的圆角处理:在咨询了一位安卓大佬后,提出了把图片的. Glide 是 Google 官方推荐的一款图片加载库,使用起来也非常的简单便利,Glide 它帮我们完成了很多很重要,但是却通用的功能,例如:图片的加载压缩、展示、加载图片的内存管理等等。 对 Glide 还不熟悉的朋友,可以参考 《一篇好文,助你上手 Glide》 但是,在使用 Glide 的时候,有一些小技巧,可以让你的... Android一般情况使用Glide加载图片,但是使用不注意就会有些问题:比较大的list的图片列表快速滚动,当前的图片需要等前面的加载才可以加载,分析如下: 1. listview的item中使用glide加载图片,当有需要对加载图片二次处理使用重新simpleTarget,然后给into,如下所示 Glide.with(mContext).load("http...