最开始的图片轮播用的是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);
}