Glide加载大量的图片导致的OOM解决总结

最开始的图片轮播用的是ViewPager+Glide,后来接触到banner,

git地址:https://github.com/youth5201314/banner

果然好用,调用方便,提供多种图片加载框架,一直用的是Glide,这里我也没有改,项目上线一个月了,突然测试发现一个问题,就是图片是概率黑屏,我一致以为是图片未下载成功,就没在意,因为老化房有一台设备,一致在运行,没有出现这个问题,后来我自己下载了4K的高清出片,来测试,果然

OOM,很好奇,Glide应该有缓存处理的工作,但是我无论怎么优化,还是OOM,

1:使用了ViewPager 仅仅初始化5个ImageView,然后复用这几个View

2:   Glide加载不添加缓存            skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE)

3: Glide加载限制图片的尺寸     override(500, 500)

整整忙乎了一整天,无解,溢出的头大,

今天出门,掐指一算,今天是个好日子,就开始google找同行有没好的方案

从studio监控的内存状态,目前系统给APP分配的内存是60M .加载10张图就差不多58M了,在加载两张必OOM。那么试试加大APP运行内存

  
这行代码就是加大APP运行内存的

果然有效,直接分配了将近200M的运行内存,一下子就解决了这个问题

在配合Glide其他的配置,后来就灭有出现OOM的情况了,

1:在清单文件里面加大APP运行内存

    

2:自定义Glide缓存尺寸这段代码我也是抄的

    

package com.etv.util.image;

import android.content.Context;

import com.bumptech.glide.Glide;
import com.bumptech.glide.GlideBuilder;
import com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool;
import com.bumptech.glide.load.engine.cache.LruResourceCache;
import com.bumptech.glide.load.engine.cache.MemorySizeCalculator;
import com.bumptech.glide.module.GlideModule;

public class CustomCachingGlideModule implements GlideModule {
    @Override
    public void applyOptions(Context context, GlideBuilder builder) {
        MemorySizeCalculator calculator = new MemorySizeCalculator(context);
        int defaultMemoryCacheSize = calculator.getMemoryCacheSize();
        int defaultBitmapPoolSize = calculator.getBitmapPoolSize();

        int customMemoryCacheSize = (int) (1.2 * defaultMemoryCacheSize);
        int customBitmapPoolSize = (int) (1.2 * defaultBitmapPoolSize);

        builder.setMemoryCache(new LruResourceCache(customMemoryCacheSize));
        builder.setBitmapPool(new LruBitmapPool(customBitmapPoolSize));
    }

    @Override
    public void registerComponents(Context context, Glide glide) {
        // nothing to do here
    }
}

3:在加载图片的时候,不要缓存资源,如果可以获取控件尺寸的话,可以控制加载的尺寸,

  override(width,height)   

            Glide.with(paramContext)
                    .load(paramObject)
                    .skipMemoryCache(true)                      //禁止Glide内存缓存
                    .diskCacheStrategy(DiskCacheStrategy.NONE)  //不缓存资源
//                    .override(500, 500)
                    .into(paramImageView);

通过以上的方法,基本可以解决OOM的问题,但是如果图片压缩就会损失图片精度,这里肯定是我们不想看见的。我们既要流畅度也要高清。这里就需要我们做内存管理,这里直接拿bannner为例子,其实和ViewPager差不多,

     banner 在数据初始化的时候就通过框架去生成图片以及加载,内存会在瞬间猛升。

    

      for (int i = 0; i <= count + 1; i++) {
            ImageView imageView = null;
            if (imageLoader != null) {
                imageView = imageLoader.createImageView(context);
            }
            if (imageView == null) {
                imageView = new ImageView(context);
            }

            imageView.setScaleType(ScaleType.FIT_XY);
            Object url = null;
            if (i == 0) {
                url = imagesUrl.get(count - 1);
            } else if (i == count + 1) {
                url = imagesUrl.get(0);
            } else {
                url = imagesUrl.get(i - 1);
            }
            imageViews.add(imageView);
            if (imageLoader != null)
                imageLoader.displayImage(context, url, imageView);
            else
                Log.e(tag, "Please set images loader.");
        }

       使用过github上的banner的伙伴,估计都遇到过OOM。

        都朝这边看 。在图片切换之后再去加载图片,图片View销毁,记得清理Glide缓存,如果灭有这一步,崩溃是早晚的事 。

       

 @Override
    public Object instantiateItem(ViewGroup container, final int position) {
        ImageView view = (ImageView) imageViews.get(position);
        String url = null;
        if (imageUrls != null && imageUrls.size() > 0) {
            if (position == 0) {
                url = imageUrls.get(imageUrls.size() - 1);
            } else if (position == imageUrls.size() + 1) {
                url = imageUrls.get(0);
            } else {
                url = imageUrls.get(position - 1);
            }
            if (imageLoader != null) {
                imageLoader.displayImage(context, url, view);
            }
        }
        view.setOnLongClickListener(
                new View.OnLongClickListener() {
                    @Override
                    public boolean onLongClick(View view) {
                        boolean osTouchOpen = SharedPerManager.isOpenTouch();
                        if (!osTouchOpen) {
                            return true;
                        }
                        if (taskPlayStateListener == null) {
                            MyLog.e("pic", "============listener==nu===");
                            return true;
                        }
                        MyLog.e("pic", "============点击了图000片===");
                        taskPlayStateListener.clickTaskView(AppInfo.VIEW_IMAGE, 0, imageUrls);
                        return true;
                    }
                });
        container.addView(view);
        return view;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        View view = (View) object;
        if (view == null) {
            return;
        }
        Glide.clear((View) object);
        container.removeView(view);
    }

 

 

你可能感兴趣的:(安卓前端,android)