由于公司APP主要是图片类应用,内存占用一直居高不下,特别是首页,全是用Glide加载的在线图,故尝试通过修改图片格式来降低内存:对于ARGB_8888的Bitmap,一个像素点存放了Alpha、Red、Green、Blue四种信息,总共4个字节,而若对透明通道没有要求,则使用RGB_565格式的,其占用2个字节,故对比起来可以节省一半的内存,代价是会损失一定的三色彩。
具体代码如下:
1.增加GlideApp配置
@GlideModule
public class AppGlide extends AppGlideModule {
@Override
public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
builder.setDefaultRequestOptions(GlideRGB565DecodeUtil.getRequestOption());
}
}
2.反射调用强行将ARGB_8888改为RGB_565
public class GlideRGB565DecodeUtil {
private static Field bmpInBitmapResource;
private static Field bmpPoolInBitmapResource;
/**
* 参考 {@link com.bumptech.glide.request.BaseRequestOptions#transform(Transformation, boolean)}
*/
public static RequestOptions getRequestOption() {
Transformation<Bitmap> transformation = new Transformation<Bitmap>() {
@NonNull
@Override
public Resource<Bitmap> transform(@NonNull Context context, @NonNull Resource<Bitmap> resource, int outWidth, int outHeight) {
Bitmap bitmap = resource.get();
if (null == bitmap)
return resource;
if (bitmap.getConfig() == Bitmap.Config.RGB_565) {
// 本身就是RGB_565的
return resource;
}
try {
if (null == bmpPoolInBitmapResource) {
bmpPoolInBitmapResource = BitmapResource.class.getDeclaredField("bitmapPool");
bmpPoolInBitmapResource.setAccessible(true);
}
if (null == bmpInBitmapResource) {
bmpInBitmapResource = BitmapResource.class.getDeclaredField("bitmap");
bmpInBitmapResource.setAccessible(true);
}
// 1.通过原图生成565的图
BitmapPool bitmapPool = (BitmapPool) bmpPoolInBitmapResource.get(resource);
Bitmap bitmap565 = bitmapPool.get(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap565);
// 设置背景色,防止透明图出现黑色的情况
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(bitmap, 0, 0, null);
// 2.使用565的图替换原图
bmpInBitmapResource.set(resource, bitmap565);
bitmapPool.put(bitmap);
} catch (Exception ignore) { }
return resource;
}
@Override
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
}
};
Transformation<Bitmap> gifTransformation = new Transformation<Bitmap>() {
@NonNull
@Override
public Resource<Bitmap> transform(@NonNull Context context, @NonNull Resource<Bitmap> resource, int outWidth, int outHeight) {
return resource;
}
@Override
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) { }
};
DrawableTransformation drawableTransformation =
new DrawableTransformation(transformation, true);
return new RequestOptions().transform(Bitmap.class, transformation)
.transform(Drawable.class, drawableTransformation)
.transform(BitmapDrawable.class, drawableTransformation.asBitmapDrawable())
// GIF不能用RGB565加载,否则会出现背景白色问题
.transform(GifDrawable.class, new GifDrawableTransformation(gifTransformation))
.format(DecodeFormat.PREFER_RGB_565);
}
public static RequestOptions getARGBRequestOption() {
return new RequestOptions().dontTransform()
.format(DecodeFormat.PREFER_ARGB_8888);
}
这样做之后便所有通过Glide加载之后的图都变成RGB_565的了,若有特殊要求需要透明的,则可如下调用即可:
GlideApp.with(context)
.asBitmap()
.apply(GlideRGB565DecodeUtil.getARGBRequestOption())
.load(target)
.into(imageView);