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

Android 自定義 View 構造函數中 originalBitmap 為 null 導致空指針異常

     編輯:程式設計綜合問答

錯誤堆疊

at com.wujiecao.face_maker.HandWrite.(HandWrite.java:44)
new1Bitmap = Bitmap.createBitmap(originalBitmap); // originalBitmap 為 null

原因分析

在 `HandWrite(Context, AttributeSet)` 構造函數中直接呼叫 `Bitmap.createBitmap(originalBitmap)`,但 `originalBitmap` 從未被賦值(僅在 `setBitmap(byte[])` 中初始化),導致傳入 `null` 拋出 `NullPointerException`。

修正方案

  1. 構造函數中不建立 Bitmap**,僅初始化畫筆、屬性等輕量操作。
  2. 在 `onSizeChanged` 或首次 `onDraw` 中依實際寬高建立 Bitmap**。
  3. 提供公開方法供外部設定圖片**,內部更新 `originalBitmap` 並 `invalidate()` 觸發重繪。

修正後完整代碼

public class HandWrite extends View {
    private Bitmap originalBitmap;
    private Bitmap drawBitmap;      // 實際繪製用的可變 Bitmap
    private Canvas drawCanvas;
    private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

    public HandWrite(Context context) { this(context, null); }
    public HandWrite(Context context, AttributeSet attrs) { this(context, attrs, 0); }
    public HandWrite(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // 僅初始化畫筆等,不建立 Bitmap
    }

    // 對外提供設定圖片
    public void setBitmap(byte[] data) {
        if (data == null) return;
        originalBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
        recreateDrawBitmap();       // 依原圖建立可繪製副本
        invalidate();
    }

    private void recreateDrawBitmap() {
        if (originalBitmap == null) return;
        // 建立同尺寸可變更 Bitmap
        drawBitmap = Bitmap.createBitmap(
                originalBitmap.getWidth(),
                originalBitmap.getHeight(),
                Bitmap.Config.ARGB_8888);
        drawCanvas = new Canvas(drawBitmap);
        // 先把原圖畫上去
        drawCanvas.drawBitmap(originalBitmap, 0, 0, paint);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // View 尺寸確定後,若無原圖可建立空白畫布
        if (drawBitmap == null) {
            drawBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            drawCanvas = new Canvas(drawBitmap);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (drawBitmap != null) {
            canvas.drawBitmap(drawBitmap, 0, 0, paint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 觸控繪製邏輯...
        invalidate();
        return true;
    }
}

關鍵點總結

錯誤做法正確做法
構造函數建立 Bitmap 依賴未初始化欄位延遲到 `onSizeChanged`/`setBitmap` 且檢查 null
直接 `onDraw(canvas)` 傳入 null絕不主動呼叫 `onDraw`,由系統在繪製流程呼叫
未釋放舊 Bitmap 導致 OOM替換前 `recycle()` 舊 Bitmap(API 19+ 可選)

總結

自定義 View **構造函數只做輕量初始化**,涉及尺寸/資源的操作放在 `onSizeChanged`、`onDraw` 或公開設定方法中,並做好 null 判斷,即可避免空指針崩潰。

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