在 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,它們已封裝了絕大多數優化邏輯。