在 Android 中加载大图时,如果不进行优化处理,很容易导致内存溢出(OOM)和应用卡顿。以下是几种高效处理大图加载的方法和最佳实践:
1. 使用图片加载库(推荐)
成熟的第三方库已经处理了内存管理、缓存和异步加载等问题,推荐使用:
- Glide
Glide.with(context).load(imageUrl).override(targetWidth, targetHeight) // 指定加载尺寸.diskCacheStrategy(DiskCacheStrategy.ALL) // 缓存优化.into(imageView)
- Picasso
Picasso.get().load(imageUrl).resize(targetWidth, targetHeight) // 缩放图片.centerInside() // 保持比例.into(imageView)
- Coil(Kotlin 协程支持)
imageView.load(imageUrl) {size(targetWidth, targetHeight)memoryCachePolicy(CachePolicy.ENABLED) }
2. 手动压缩图片(Bitmap 优化)
如果必须直接操作 Bitmap
,需通过以下步骤减少内存占用:
(1) 获取图片尺寸(不加载内存)
val options = BitmapFactory.Options().apply {inJustDecodeBounds = true // 只解码边界信息
}
BitmapFactory.decodeFile(imagePath, options)
val (width, height) = options.outWidth to options.outHeight
(2) 计算缩放比例(inSampleSize)
fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {val (height, width) = options.outHeight to options.outWidthvar inSampleSize = 1if (height > reqHeight || width > reqWidth) {val halfHeight = height / 2val halfWidth = width / 2// 计算最大 inSampleSize 保证缩放后尺寸仍大于目标值while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {inSampleSize *= 2}}return inSampleSize
}
(3) 加载压缩后的 Bitmap
val options = BitmapFactory.Options().apply {inSampleSize = calculateInSampleSize(/* 目标尺寸 */)inPreferredConfig = Bitmap.Config.RGB_565 // 减少内存(每个像素占2字节)
}
val bitmap = BitmapFactory.decodeFile(imagePath, options)
imageView.setImageBitmap(bitmap)
3. 分块加载超大图(区域解码)
对于超大型图片(如地图、高清壁画),使用 BitmapRegionDecoder
分区域加载:
val decoder = BitmapRegionDecoder.newInstance(inputStream, false)
val rect = Rect(startX, startY, endX, endY) // 目标区域坐标
val options = BitmapFactory.Options().apply {inPreferredConfig = Bitmap.Config.RGB_565
}
val regionBitmap = decoder.decodeRegion(rect, options)
imageView.setImageBitmap(regionBitmap)
4. 内存管理技巧
- 及时回收 Bitmap:
if (!bitmap.isRecycled) {bitmap.recycle() // 主动释放 Native 内存 }
- 使用
WeakReference
:避免 Activity 泄漏。 - 开启大堆(谨慎使用):
在AndroidManifest.xml
中为 Activity 添加:<application android:largeHeap="true">
5. 其他优化策略
- 磁盘缓存:避免重复解码。
- 列表中使用缩略图:如 RecyclerView 优先加载低分辨率图。
- 监听生命周期:在
onDestroy
中取消加载(Glide 自动支持)。
总结流程图
加载图片 → 检查缓存 → 计算目标尺寸 → 缩放/分块解码 → 显示↑(内存/磁盘缓存)
通过合理使用库或手动优化,可以高效加载大图而不影响性能。推荐优先选择 Glide 或 Coil,它们已封装了绝大多数优化逻辑。