多次用Glide加载Bitmap至CropperImageView引发OOM问题求助
解决Glide加载Bitmap导致的OutOfMemory异常问题
我完全懂你遇到的麻烦——多次切换RecyclerView里的图片后,Glide因为加载高分辨率原图抛出OOM,这在处理手机拍摄的大尺寸图片时太常见了。下面是几个针对性的解决方案,按优先级排序:
1. 让Glide根据CropperImageView的实际尺寸缩放图片
这是最核心的优化点:相机拍摄的图片动辄几百万像素(比如你日志里的图片需要分配近50MB内存),但CropperImageView的实际显示尺寸远小于这个值,直接加载原图纯粹是浪费内存。
修改你的Glide加载代码,添加override()方法指定目标视图的宽高:
// 获取CropperImageView的实际显示尺寸 int targetWidth = cropperView.getWidth(); int targetHeight = cropperView.getHeight(); // 如果视图还未完成测量(比如页面刚初始化),用屏幕尺寸兜底 if (targetWidth == 0 || targetHeight == 0) { DisplayMetrics metrics = getContext().getResources().getDisplayMetrics(); targetWidth = metrics.widthPixels; targetHeight = metrics.heightPixels; } Glide.with(getContext()) .asBitmap() .load(imageFilePath) // 强制Glide将图片缩放到目标尺寸,大幅降低内存占用 .override(targetWidth, targetHeight) // 保持图片比例,避免拉伸变形 .fitCenter() .into(new SimpleTarget<Bitmap>() { @Override public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) { // 先回收旧Bitmap,避免内存堆积 Bitmap oldBitmap = cropperView.getBitmap(); if (oldBitmap != null && !oldBitmap.isRecycled()) { oldBitmap.recycle(); } cropperView.setImageBitmap(resource); } });
2. 替换SimpleTarget为ViewTarget(更推荐)
SimpleTarget如果没有妥善管理,容易引发内存泄漏或多余的内存占用。改用ViewTarget可以让Glide自动绑定视图生命周期,更安全高效:
Glide.with(getContext()) .asBitmap() .load(imageFilePath) .override(targetWidth, targetHeight) .fitCenter() .into(new ViewTarget<CropperImageView, Bitmap>(cropperView) { @Override public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) { Bitmap oldBitmap = this.view.getBitmap(); if (oldBitmap != null && !oldBitmap.isRecycled()) { oldBitmap.recycle(); } this.view.setImageBitmap(resource); } });
3. 配置Glide全局内存缓存与Bitmap池
在自定义的AppGlideModule里调整内存缓存和Bitmap池大小,让Glide更高效地复用Bitmap,减少重复内存分配:
@GlideModule public class MyAppGlideModule extends AppGlideModule { @Override public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) { // 取设备可用内存的1/8作为Glide内存缓存与Bitmap池的大小 int memorySizeBytes = (int) (Runtime.getRuntime().maxMemory() / 8); builder.setMemoryCache(new LruResourceCache(memorySizeBytes)); builder.setBitmapPool(new LruBitmapPool(memorySizeBytes)); } }
4. 页面销毁时清理资源
在页面的onDestroy()方法里,主动清理CropperImageView的Bitmap和Glide的加载任务,避免内存泄漏:
@Override protected void onDestroy() { super.onDestroy(); // 回收CropperImageView的Bitmap Bitmap bitmap = cropperView.getBitmap(); if (bitmap != null && !bitmap.isRecycled()) { bitmap.recycle(); } // 取消Glide所有未完成的加载任务 Glide.with(this).clear(cropperView); }
内容的提问来源于stack exchange,提问作者Fahime Ghasemi
相关产品推荐
相关产品推荐

