获取imageView空引用错误-为什么会这样?

时间:2018-10-26 10:50:46

标签: android android-layout android-canvas

我正在图像视图上绘制可调整大小的矩形。

用于绘制自定义可缩放矩形视图的View类:

public class DrawPolygonCanvas extends View implements OnTouchListener {

    private final String TAG = "DrawLineCanvas";
    private final String defaultROI = "Roi1:0.2,0.2|0.8,0.2|0.8,0.8|0.2,0.8";
    private Context context;
    private CanvasTouchManager canvasTouchManager = new CanvasTouchManager();
    private boolean isInitialized = false;
    private Paint circlePaint, linePaint;
    private String cameraROI = "";

    // Debug helpers to draw lines between the two touch points
    private HashMap<String, List<Vector2D>> polygons = new HashMap();

    public DrawPolygonCanvas(Context context) {
        super(context);
        init(context);
    }

    public DrawPolygonCanvas(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public DrawPolygonCanvas(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    public DrawPolygonCanvas(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context);
    }

    private void init(Context context) {
        Log.e(TAG, "called init");
        this.context = context;
        Log.e(TAG, "calling setOnTouchListener");
        setOnTouchListener(this);
    }

    public void clearROI() {
        Log.e(TAG, "called clearROI");
        // Get ROI from the shared preferences.
        SharedPreferences prefs = UserSharedPref.initializeSharedPreferencesForCameraROI(context);
        cameraROI = prefs.getString(UserSharedPref.cameraROI, cameraROI);
        Log.e(TAG, "Reloaded ROI = " + cameraROI);
        convertString2Polygons();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Log.e(TAG, "called onDraw");
        super.onDraw(canvas);

        if (!isInitialized) {
            // Get ROI from the shared preferences.
            SharedPreferences prefs = UserSharedPref.initializeSharedPreferencesForCameraROI(context);
            cameraROI = prefs.getString(UserSharedPref.cameraROI, cameraROI);
            if (cameraROI.isEmpty()) {
                cameraROI = defaultROI;
            }
            convertString2Polygons();

            circlePaint = new Paint();
            circlePaint.setColor(0xFFFF0000);

            linePaint = new Paint();
            linePaint.setColor(0xFF00FF00);
            linePaint.setStyle(Paint.Style.STROKE);
            linePaint.setStrokeWidth(10);

            isInitialized = true;
        }

        Rect dest = new Rect(0, 0, getWidth(), getHeight());
        Paint paint = new Paint();
        paint.setFilterBitmap(true);


        exampleActivity ex = new exampleActivity();
        Bitmap bm = ex.getBitmap();

        canvas.drawBitmap(bm, null, dest, paint);

        try {
            for (Map.Entry<String, List<Vector2D>> entry : polygons.entrySet()) {

                List<Vector2D> polygon = entry.getValue();

                for (int i = 0; i < polygon.size() - 1; i++) {
                    canvas.drawLine(polygon.get(i).getX(), polygon.get(i).getY(), polygon.get(i + 1).getX(), polygon.get(i + 1).getY(), linePaint);
                }
                canvas.drawLine(polygon.get(polygon.size() - 1).getX(), polygon.get(polygon.size() - 1).getY(), polygon.get(0).getX(), polygon.get(0).getY(), linePaint);

                for (int i = 0; i < polygon.size(); i++) {
                    canvas.drawCircle(polygon.get(i).getX(), polygon.get(i).getY(), 40, circlePaint);
                }
            }
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDetachedFromWindow() {
        Log.e(TAG, "called onDetachedFromWindow");
        super.onDetachedFromWindow();

        // Convert polygon back to string.
        convertPolygons2String();

        SharedPreferences.Editor editor = UserSharedPref.initializeSharedPreferencesForCameraROI(context).edit();
        editor.putString(UserSharedPref.cameraROI, cameraROI);
        editor.apply();
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.e(TAG, "called onTouch");
        canvasTouchManager.update(event);
        Vector2D vct = canvasTouchManager.getPoint();

        float minDist = 200000.0f;
        float radius = 200;

        int minIndex = -1;
        String key = "";

        for (Map.Entry<String, List<Vector2D>> entry : polygons.entrySet()) {

            List<Vector2D> points = entry.getValue();
            for (int i = 0; i < points.size(); i++) {
                float dist = points.get(i) == null ? 0 : Vector2D.subtract(vct, points.get(i)).getLength();
                if (dist >= radius) {
                    continue;
                }

                if (dist < minDist) {
                    minDist = dist;
                    minIndex = i;
                    Log.e(TAG, "Matching x = " + points.get(i).getX() + ", y = " + points.get(i).getY());
                    key = entry.getKey();
                }
            }
        }

        if (minIndex != -1 && !key.isEmpty()) {
            polygons.get(key).set(minIndex, vct);
        } else {
            Log.e("OK2", "Touch point is too far, dist = " + minDist);
        }

        invalidate();

        return true;
    }

    private void convertPolygons2String() {
        cameraROI = "";
        for (Map.Entry<String, List<Vector2D>> entry : polygons.entrySet()) {
            cameraROI += cameraROI.isEmpty() ? entry.getKey() + ":" : ";" + entry.getKey() + ":";
            List<Vector2D> points = entry.getValue();
            for (int i = 0; i < points.size(); i++) {
                float x = points.get(i).getX() / (float) getWidth();
                float y = points.get(i).getY() / (float) getHeight();

                cameraROI += String.format("%.2f", x);
                cameraROI += ",";
                cameraROI += String.format("%.2f", y);

                if (i < points.size() - 1) {
                    cameraROI += "|";
                }
            }
        }

        Log.e(TAG, "Converted string = " + cameraROI);
    }

    private void convertString2Polygons() {
        Log.e(TAG, "called  convertString2Polygons");
        String[] ROIs = cameraROI.split(";");
        if (cameraROI.isEmpty() || ROIs.length == 0) {
            Log.e(TAG, "No polygon is configured.");
            polygons.clear();
            return;
        }

        // Parse and add each polygon
        for (String roi : ROIs) {
            String[] polygonString = roi.split(":");
            if (polygonString.length != 2) {
                continue;
            }

            String[] vertices = polygonString[1].split("\\|");
            if (vertices.length < 3) {
                Log.d(TAG, polygonString[1] + " is not a valid polygon setting, which needs at least 3 vertices, e.g '0,5,0.1|0.3,0.4|0.5,0.6|0.7,0.8'.");
                return;
            }

            List<Vector2D> points = new ArrayList<>();
            for (String vertex : vertices) {
                Log.d(TAG, "Vertex = " + vertex);
                String[] vertexString = vertex.split(",");
                if (vertexString.length != 2) {
                    Log.d(TAG, vertex + " is not a valid vertex setting. An example should look like '0.5,0.5'.");
                    return;
                }

                try {
                    float x = Float.parseFloat(vertexString[0]);
                    float y = Float.parseFloat(vertexString[1]);

                    points.add(new Vector2D(x * getWidth(), y * getHeight()));

                    Log.d(TAG, "Adding [" + x + ", " + y + "]");
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                    Log.d(TAG, vertex + " is invalid. Vertex's X and Y coordinates should be float numbers.");
                    return;
                }
            }

            polygons.put(polygonString[0], points);
            Log.d(TAG, "Add configured polygon: " + polygonString[0] + " - " + polygonString[1]);
        }
    }
}

这是我的XML文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".exampleActivity">



    <ImageView
        android:id="@+id/office"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@string/office"
        android:src="@raw/office" />

    <com.lambdahash.sonic.example.draw.senapr.DrawPolygonCanvas
        android:id="@+id/DrawPolygonCanvas"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>

最后,这就是我将视图附加到xml文件(活动)的方式:

public class exampleActivity extends Activity {

private ImageView img;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_example);
        DrawPolygonCanvas canvas = (DrawPolygonCanvas) findViewById(R.id.DrawPolygonCanvas);

        img = (ImageView) findViewById(R.id.office);
       }

public Bitmap getBitmap(){
    Bitmap bm = ((BitmapDrawable) img.getDrawable()).getBitmap();
    return bm;
}


    public void onReset(View v) {
        DrawPolygonCanvas canvas = (DrawPolygonCanvas) findViewById(R.id.DrawPolygonCanvas);
        SharedPreferences.Editor editor = UserSharedPref.initializeSharedPreferencesForCameraROI(canvas.getContext()).edit();
        editor.putString(UserSharedPref.cameraROI, "");
        editor.apply();
        canvas.clearROI();
    }
}

基本上,这段代码中最重要的部分是 DrawPolygonCanvas 中的 onDraw()出现问题时,这些行, exampleActivity ex = new exampleActivity();Bitmap bm = ex.getBitmap();所产生的错误是:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.graphics.drawable.Drawable android.widget.ImageView.getDrawable()' on a null object reference

由于某种原因,XML文件中的imageView尚未初始化。 我该如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

exampleActivity ex = new exampleActivity();
Bitmap bm = ex.getBitmap();

根本原因:由于您正在创建ExampleActivity的新实例,因此所有活动回调方法,例如onCreateonStart,{{1} }等不会被调用。对于您而言,因为onResume从未打电话给您,为什么您的onCreate总是img。结果,当您在其上调用null方法时,Android将抛出NullPointerException

getDrawable

提示:永远不要在Android中创建Activity的实例,您要做的就是在AndroidManifest.xml文件中注册该活动,然后在Activity回调方法中编写您的代码。

解决方案:返回您的案例,要从Activity中获取位图,您可以实现一个侦听器接口,以将位图从java.lang.NullPointerException: Attempt to invoke virtual method 'android.graphics.drawable.Drawable android.widget.ImageView.getDrawable()' on a null object reference. 传递到exampleActivity

DrawPolygonCanvas

DrawPolygonCanvas

exampleActivity

public class DrawPolygonCanvas extends View implements OnTouchListener{

    public interface OnGetBitmapListener {
        Bitmap onGetBitmap();
    }

    private OnGetBitmapListener mOnGetBitmapListener;

    public void setOnGetBitmapListener(OnGetBitmapListener listener) {
        mOnGetBitmapListener = listener;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Log.e(TAG, "called onDraw");
        super.onDraw(canvas);
        paint.setFilterBitmap(true);

        // Add these lines
        Bitmap bm = null;
        if (mOnGetBitmapListener != null) {
            bm = mOnGetBitmapListener.onGetBitmap();
        }

        canvas.drawBitmap(bm, null, dest, paint);
    }
}