首页 > 解决方案 > Android 应用程序已停止并尝试在空对象引用上调用虚拟方法

问题描述

当我运行我的 android 应用程序时,它崩溃并说 Android 应用程序已停止。它还给出了这个错误信息:

java.lang.NullPointerException: Attempt to invoke virtual method 'com.esimerkki.doodl2.DoodleView com.esimerkki.doodl2.FirstFragment.getDoodleView()' on a null object reference

这有什么问题?引用真的为空吗?我怎样才能使这项工作?我认为 doodleView 中的这些原始设置有起始值吗?

这是 doodleView 类的代码:

package com.esimerkki.doodl2;

import android.content.Context;
import android.view.View;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.provider.MediaStore;

import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.widget.Toast;

import androidx.print.PrintHelper;

import java.util.HashMap;
import java.util.Map;

public class DoodleView extends View {

    public DoodleView(Context context, Paint paintScreen, Paint paintLine) {
        super( context );
        this.paintScreen = paintScreen;
        this.paintLine = paintLine;
    }

    private static final float TOUCH_TOLERANCE = 10;

    private Bitmap bitmap; // drawing area
    private Canvas bitmapCanvas; // 
    private final Paint paintScreen; // 
    private final Paint paintLine; // 

   
    private final Map<Integer, Path> pathMap = new HashMap<>();
    private final Map<Integer, Point> previousPointMap = new HashMap<>();


    public DoodleView(Context context, AttributeSet attrs) {
        super(context, attrs); // kutsutaan yliluokanalustajaa
        paintScreen = new Paint(); // bittikartan näyttämiseen ruudulla

      
        paintLine = new Paint();
        paintLine.setAntiAlias(true); 
        paintLine.setColor(Color.BLACK); 
        paintLine.setStyle(Paint.Style.STROKE); 
        paintLine.setStrokeWidth(5); 
        paintLine.setStrokeCap(Paint.Cap.ROUND); 
   
    @Override
    public void onSizeChanged(int w, int h, int OldW, int oldH) {
        bitmap = Bitmap.createBitmap(getWidth(), getHeight(),
                Bitmap.Config.ARGB_8888); 
        bitmapCanvas = new Canvas(bitmap);
        bitmap.eraseColor(Color.WHITE); 
    }

    
    public void clear() {
        pathMap.clear(); 
        previousPointMap.clear(); 
        bitmap.eraseColor(Color.WHITE); 
        invalidate(); 
    }

  
    public void setDrawingColor(int color) {
        paintLine.setColor(color);
    }

  
    public int getDrawingColor() {
        return paintLine.getColor();
    }

    public void setLineWidth(int width) {
        paintLine.setStrokeWidth(width);
    }

   
    public int getLineWidth() {
        return (int) paintLine.getStrokeWidth();
    }

    @Override
    protected void onDraw(Canvas canvas) {
       
        canvas.drawBitmap(bitmap, 0, 0, paintScreen);

        for (Integer key : pathMap.keySet())
            canvas.drawPath(pathMap.get(key), paintLine); // piirretään viiva
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getActionMasked(); // tapahtumatyyppi
        int actionIndex = event.getActionIndex(); // osoitin

        if (action == MotionEvent.ACTION_DOWN ||
                action == MotionEvent.ACTION_POINTER_DOWN) {
            touchStarted(event.getX(actionIndex), event.getY(actionIndex),
                    event.getPointerId(actionIndex));
        }
        else if (action == MotionEvent.ACTION_UP ||
                action == MotionEvent.ACTION_POINTER_UP) {
            touchEnded(event.getPointerId(actionIndex));
        }
        else {
            touchMoved(event);
        }

        invalidate(); 
        return true;
    }

   
    private void touchStarted(float x, float y, int lineID) {
        Path path; // tallennetaan tietyn id:n polku
        Point point; // tallennetaan polun viimeinen piste

       
        if (pathMap.containsKey(lineID)) {
            path = pathMap.get(lineID); 
            path.reset(); 
            point = previousPointMap.get(lineID); 
        }
        else {
            path = new Path();
            pathMap.put(lineID, path);
            point = new Point(); 
            previousPointMap.put(lineID, point); 
        }

        path.moveTo(x, y);
        point.x = (int) x;
        point.y = (int) y;
    }

    private void touchMoved(MotionEvent event) {
        
        for (int i = 0; i < event.getPointerCount(); i++) {
            // luetaan pointtein id ja indeksi
            int pointerID = event.getPointerId(i);
            int pointerIndex = event.findPointerIndex(pointerID);

         
            if (pathMap.containsKey(pointerID)) {
            
                float newX = event.getX(pointerIndex);
                float newY = event.getY(pointerIndex);

                Path path = pathMap.get(pointerID);
                Point point = previousPointMap.get(pointerID);
                // lasketaan kuinka kauas liikuttu
                float deltaX = Math.abs(newX - point.x);
                float deltaY = Math.abs(newY - point.y);

                if (deltaX >= TOUCH_TOLERANCE || deltaY >= TOUCH_TOLERANCE) {
            
                    path.quadTo(point.x, point.y, (newX + point.x) / 2,
                            (newY + point.y) / 2);

                 
                    point.x = (int) newX;
                    point.y = (int) newY;
                }
            }
        }
    }

    private void touchEnded(int lineID) {
        Path path = pathMap.get(lineID); 
        bitmapCanvas.drawPath(path, paintLine); 
        path.reset(); // tyhjennetään polku
    }

 
    public void saveImage() {
    
        final String name = "Doodlz" + System.currentTimeMillis() + ".jpg";

        String location = MediaStore.Images.Media.insertImage(
                getContext().getContentResolver(), bitmap, name,
                "Doodlz Drawing"
        );

        if (location != null) {
          
            Toast message = Toast.makeText(getContext(),
                    R.string.message_saved,
                    Toast.LENGTH_SHORT);
            message.setGravity(Gravity.CENTER, message.getXOffset() / 2,
                    message.getYOffset() / 2);
            message.show();
        }
        else {
          
            Toast message = Toast.makeText(getContext(),
                    R.string.message_error_saving, Toast.LENGTH_SHORT);
            message.setGravity(Gravity.CENTER, message.getXOffset() / 2,
                    message.getYOffset() / 2);
            message.show();
        }
    }

    public void printImage() {
        if (PrintHelper.systemSupportsPrint()) {
          
            PrintHelper printHelper = new PrintHelper(getContext());

            printHelper.setScaleMode(printHelper.SCALE_MODE_FIT);
            printHelper.printBitmap("Doodlz Imate", bitmap);
        }
        else {
         
            Toast message = Toast.makeText(getContext(),
                    R.string.message_error_printing, Toast.LENGTH_SHORT);
            message.setGravity(Gravity.CENTER, message.getXOffset() / 2,
                    message.getYOffset() / 2);
            message.show();
        }
    }


}    

这是 LineWidthFragment 类的代码:

package com.esimerkki.doodl2;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
//import android.support.v4.app.DialogFragment;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;

import androidx.fragment.app.DialogFragment;

public class LineWidthFragment extends DialogFragment {

    private ImageView widthImageView;

    @Override
    public Dialog onCreateDialog(Bundle bundle) {
        
        AlertDialog.Builder builder =
                new AlertDialog.Builder(getActivity());
        View lineWidthDialogView =
                getActivity().getLayoutInflater().inflate(
                        R.layout.fragment_line_width, null);
        builder.setView(lineWidthDialogView); // lisätään GUI dialogiin

      
        builder.setTitle(R.string.title_line_width_dialog);

     
        widthImageView = (ImageView) lineWidthDialogView.findViewById(
                R.id.widthImageView);

     
        final DoodleView doodleView = getDoodleFragment().getDoodleView();
    
        final SeekBar widthSeekBar = (SeekBar)
                lineWidthDialogView.findViewById(R.id.widthSeekBar);
        widthSeekBar.setOnSeekBarChangeListener(lineWidthChanged);
        widthSeekBar.setProgress(doodleView.getLineWidth());


        builder.setPositiveButton(R.string.button_set_line_width,
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                        doodleView.setLineWidth(widthSeekBar.getProgress());
                    }
                }
        );
        return builder.create();
    }

    private FirstFragment getDoodleFragment() {
        return (FirstFragment) getChildFragmentManager().findFragmentById(
                R.id.doodleFragment);
    }


    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        FirstFragment fragment = getDoodleFragment();

        if (fragment != null)
            fragment.setDialogOnScreen(true);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        FirstFragment fragment = getDoodleFragment();

        if (fragment != null)
            fragment.setDialogOnScreen(false);
    }

    
    private final OnSeekBarChangeListener lineWidthChanged =
            new OnSeekBarChangeListener() {
                final Bitmap bitmap = Bitmap.createBitmap(
                        400, 100, Bitmap.Config.ARGB_8888);
                final Canvas canvas = new Canvas(bitmap); // piirtää bittikarttaan

                @Override
                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                    Paint p = new Paint();
                    p.setColor(
                            getDoodleFragment().getDoodleView().getDrawingColor());
                    p.setStrokeCap(Paint.Cap.ROUND);
                    p.setStrokeWidth(progress);

                    bitmap.eraseColor(
                            getResources().getColor(android.R.color.transparent,
                                    getContext().getTheme()));
                    canvas.drawLine(30, 50, 370, 50, p);
                    widthImageView.setImageBitmap(bitmap);
                }

                @Override
                public void onStartTrackingTouch(SeekBar seekBar) { // tarvitaan

                }

                @Override
                public void onStopTrackingTouch(SeekBar seekBar) { // tarvitaan

                }
            };

}

标签: androidandroid-studio

解决方案


您的错误内容如下: null object reference

这意味着1 个对象的值为 0。您的代码看起来不错,但如果您再次重写代码,您可能会解决错误。这是由您的代码中的一个小错误引起的。重写的时候。你可以找到那个错误。即使这是某些插件或其他任何东西的错误。同样在您重写它之后,如果您遇到相同的错误,那么您需要查看参考。


推荐阅读