首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Android 圖片加載優化:inSampleSize 計算原理與最佳實踐

     編輯:程式設計疑難解答

參數含義

BitmapFactory.Options.inSampleSize:解碼縮放因子。值為 N (N>0) 時,解碼器對原圖進行 1/N 采樣,輸出圖寬高約為原圖的 1/N,內存佔用約為 1/N²。

  • inSampleSize = 1:原尺寸(默認)。
  • inSampleSize = 2:寬高各縮半,像素數 1/4。
  • inSampleSize = 4:寬高各 1/4,像素數 1/16。

標準兩步加載流程

// 1. 僅獲取尺寸,不分配像素內存
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, opts); // opts.outWidth/outHeight 已填充

// 2. 計算合適的 inSampleSize
opts.inSampleSize = calculateInSampleSize(opts, reqWidth, reqHeight);

// 3. 真正解碼
opts.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(filePath, opts);

經典計算算法(Google 官方推薦)

public static int calculateInSampleSize(BitmapFactory.Options options,
                                        int reqWidth, int reqHeight) {
    // 原始尺寸
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // 縮放後的尺寸仍大於需求尺寸時,繼續放大 inSampleSize
        while ((halfHeight / inSampleSize) >= reqHeight
                && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }
    return inSampleSize;
}

關鍵細節

細節說明
只能是 2 的冪次解碼器實現限制,非 2 的冪次會向下取整到最近的 2 的冪次。
reqWidth/reqHeight 來源通常取 ImageView 的 getMeasuredWidth/Height 或螢幕尺寸。
OOM 仍發生?檢查是否重複持有 Bitmap 引用、是否調用 recycle()(API<19)、使用 inBitmap 復用內存(API 19+)。
圖片旋轉問題inSampleSize 不處理 EXIF 旋轉,需配合 ExifInterface 矩正。

現代替代方案

生產項目建議直接使用成熟圖片庫,內部已封裝最佳策略:

  • Glide:Glide.with(ctx).load(path).override(w,h).into(iv);
  • Coil (Kotlin):iv.load(path) { crossfade(true) }
  • Fresco:支援 WebP、漸進式 JPEG、共享內存區。

理解 inSampleSize 原理是優化內存的基礎,實戰中請站在巨人肩膀上。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved