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

Android Bitmap 記憶體溢出:正確回收時機與替代方案

     編輯:程式設計綜合問答

問題場景

public Bitmap rotateBitmap(int degree, Bitmap bitmap) {
    Matrix matrix = new Matrix();
    matrix.postRotate(degree);
    Bitmap bm = Bitmap.createBitmap(bitmap, 0, 0, 
                    bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    return bm; // 呼叫端若不及時 recycle 會導致 OOM
}

錯誤做法

在 return bm; 前呼叫 bm.recycle() 會導致回傳的 Bitmap 已被回收,ImageView 顯示黑色或崩潰。

正確回收策略

  1. 呼叫端負責回收:建立新 Bitmap 後,舊 Bitmap 由呼叫端在不再需要時回收。
    // 呼叫端
    Bitmap oldBitmap = imageView.getDrawable() instanceof BitmapDrawable ? 
                       ((BitmapDrawable)imageView.getDrawable()).getBitmap() : null;
    Bitmap newBitmap = rotateBitmap(90, oldBitmap);
    imageView.setImageBitmap(newBitmap);
    if (oldBitmap != null && oldBitmap != newBitmap && !oldBitmap.isRecycled()) {
        oldBitmap.recycle();
    }
  2. 使用 inBitmap 重用記憶體 (API 19+):
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inMutable = true;
    options.inBitmap = oldBitmap; // 重用舊記憶體塊
    Bitmap newBitmap = Bitmap.createBitmap(...); // 需相容尺寸/配置
  3. 改用 Canvas 繪製避免創建新 Bitmap:
    public void rotateAndDraw(Canvas canvas, Bitmap bitmap, int degree) {
        canvas.save();
        canvas.rotate(degree, bitmap.getWidth()/2, bitmap.getHeight()/2);
        canvas.drawBitmap(bitmap, 0, 0, null);
        canvas.restore();
    }

最佳實踐總結

  • 「誰創建,誰負責回收」原則:工具方法只負責創建/轉換,生命週期由持有者管理。
  • 使用 LruCache 快取常用 Bitmap,減少重複解碼。
  • 大圖載入時使用 inSampleSize 縮放至螢幕尺寸。
  • Android 8.0+ Bitmap 像素資料移至 Native Heap,recycle() 只是提示 GC,不再立即釋放。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved