简体   繁体   English

Android:尝试将已保存的位图数据加载到Canvas时,Android应用程序崩溃

[英]Android: Android app crashing when trying to load saved Bitmap data to Canvas

First of all thanks in advance for the help. 首先,首先感谢您的帮助。 My app is basically a sketchbook with multiple canvas. 我的应用基本上是带有多个画布的写生簿。 Here after drawing on first canvas and when I click on Next button new canvas is loaded and previous canvas is saved into an Bitmap array. 在第一个画布上绘制后,当我单击“ 下一步”按钮时,将加载新画布,并将先前的画布保存到Bitmap数组中。 After drawing on the new canvas that has been loaded, when I click on Prev button, the present drawing is saved in bitmap array and the new canvas should load the previously drawn image onto canvas. 在已加载的新画布上绘制后,当我单击“上一步”按钮时,当前图形将保存在位图数组中,新画布应将先前绘制的图像加载到画布上。

But instead of that when i click on Prev button the app is crashing. 但是,相反,当我单击“上一步”按钮时,应用程序崩溃了。

Please help me with this issue. 请帮我解决这个问题。

Here is the code of both Next and Prev buttons. 这是“ 下一步”和“上一步”按钮的代码。

Next Button 下一个按钮

if(view.getId()==R.id.next){
        bitArrayStore(i);
        drawView.startNew();
        i++;
    }

Prev Button 上一页按钮

if(view.getId() == R.id.prev){
        bitArrayStore(i);
        drawView.startNew();
        i--;
        drawView.redraw(bits, i);
    }

bitArrayStore() bitArrayStore()

 public void bitArrayStore(int k){

    drawView.buildDrawingCache();
    drawView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
    bits[k] = drawView.getDrawingCache();
    drawView.destroyDrawingCache();
}

drawView.redraw() drawView.redraw()

 public void redraw(Bitmap[] bits, int i) {
    drawCanvas.drawBitmap(bits[i], 0, 0, null);
    invalidate();
}

Here is my logcat 这是我的日志

10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: FATAL EXCEPTION: main
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: Process: com.example.jishnu.notestest, PID: 18856
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@c0446aa
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime:     at android.graphics.Canvas.throwIfCannotDraw(Canvas.java:1282)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime:     at android.graphics.Canvas.drawBitmap(Canvas.java:1337)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime:     at com.example.jishnu.notestest.DrawingView.redraw(DrawingView.java:136)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime:     at com.example.jishnu.notestest.MainActivity.onClick(MainActivity.java:245)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime:     at android.view.View.performClick(View.java:4780)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime:     at android.view.View$PerformClick.run(View.java:19866)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime:     at android.os.Handler.handleCallback(Handler.java:739)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:95)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:135)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5254)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:372)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

Here is my rest of the code in case of reference 这是我剩下的代码,以供参考

MainActivity.java MainActivity.java

public class MainActivity extends AppCompatActivity implements OnClickListener {

    private DrawingView drawView;
    private ImageButton currPaint,drawBtn,eraseBtn,newBtn,saveBtn;
    private float smallBrush, mediumBrush, largeBrush;
    String ucolor;
    private Button nextbtn,prevbtn;
    int i=0;
    Bitmap[] bits;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        drawView = (DrawingView) findViewById(R.id.drawing);
        LinearLayout paintLayout = (LinearLayout) findViewById(R.id.paint_colors);
        currPaint = (ImageButton) paintLayout.getChildAt(0);
        currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
        smallBrush = getResources().getInteger(R.integer.small_size);
        mediumBrush = getResources().getInteger(R.integer.medium_size);
        largeBrush = getResources().getInteger(R.integer.large_size);
        drawBtn = (ImageButton)findViewById(R.id.draw_btn);
        drawBtn.setOnClickListener(this);
        drawView.setBrushSize(mediumBrush);
        eraseBtn = (ImageButton)findViewById(R.id.erase_btn);
        eraseBtn.setOnClickListener(this);
        newBtn = (ImageButton)findViewById(R.id.new_btn);
        newBtn.setOnClickListener(this);
        saveBtn = (ImageButton)findViewById(R.id.save_btn);
        saveBtn.setOnClickListener(this);

        bits=new Bitmap[40];
        nextbtn=(Button)findViewById(R.id.next);
        prevbtn=(Button)findViewById(R.id.prev);
        nextbtn.setOnClickListener(this);
        prevbtn.setOnClickListener(this);
        drawView.setDrawingCacheEnabled(true);

    }

    public void paintClicked(View view) {
        //use chosen color

        drawView.setErase(false);
        drawView.setBrushSize(drawView.getLastBrushSize());
        if (view != currPaint) {

            ImageButton imgView = (ImageButton)view;
            String color = view.getTag().toString();
            drawView.setColor(color);

            imgView.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
            currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint));
            currPaint=(ImageButton)view;
        }
    }

    @Override
    public void onClick(View view) {
        if(view.getId()==R.id.draw_btn){
            //draw button clicked
            final Dialog brushDialog = new Dialog(this);
            brushDialog.setTitle("Brush size:");
            brushDialog.setContentView(R.layout.brush_chooser);
            ImageButton smallBtn = (ImageButton)brushDialog.findViewById(R.id.small_brush);
            smallBtn.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    drawView.setBrushSize(smallBrush);
                    drawView.setLastBrushSize(smallBrush);
                    drawView.setErase(false);

                    brushDialog.dismiss();
                }
            });
            ImageButton mediumBtn = (ImageButton)brushDialog.findViewById(R.id.medium_brush);
            mediumBtn.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    drawView.setBrushSize(mediumBrush);
                    drawView.setLastBrushSize(mediumBrush);
                    drawView.setErase(false);

                    brushDialog.dismiss();
                }
            });

            ImageButton largeBtn = (ImageButton)brushDialog.findViewById(R.id.large_brush);
            largeBtn.setOnClickListener(new OnClickListener(){
                @Override
                public void onClick(View v) {
                    drawView.setBrushSize(largeBrush);
                    drawView.setLastBrushSize(largeBrush);
                    drawView.setErase(false);

                    brushDialog.dismiss();
                }
            });
            brushDialog.show();
        }
        else if(view.getId()==R.id.erase_btn){
            //switch to erase - choose size
            final Dialog brushDialog = new Dialog(this);
            brushDialog.setTitle("Eraser size:");
            brushDialog.setContentView(R.layout.brush_chooser);
            ImageButton smallBtn = (ImageButton)brushDialog.findViewById(R.id.small_brush);
            smallBtn.setOnClickListener(new OnClickListener(){
                @Override
                public void onClick(View v) {
                    drawView.setErase(true);
                    drawView.setBrushSize(smallBrush);
                    brushDialog.dismiss();
                }
            });
            ImageButton mediumBtn = (ImageButton)brushDialog.findViewById(R.id.medium_brush);
            mediumBtn.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    drawView.setErase(true);
                    drawView.setBrushSize(mediumBrush);
                    brushDialog.dismiss();
                }
            });
            ImageButton largeBtn = (ImageButton)brushDialog.findViewById(R.id.large_brush);
            largeBtn.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    drawView.setErase(true);
                    drawView.setBrushSize(largeBrush);
                    brushDialog.dismiss();
                }
            });
            brushDialog.show();
        }
        else if(view.getId()==R.id.new_btn){
            //new button
            AlertDialog.Builder newDialog = new AlertDialog.Builder(this);
            newDialog.setTitle("New drawing");
            newDialog.setMessage("Start new drawing (you will lose the current drawing)?");
            newDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
                public void onClick(DialogInterface dialog, int which){
                    drawView.startNew();
                    dialog.dismiss();
                }
            });
            newDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
                public void onClick(DialogInterface dialog, int which){
                    dialog.cancel();
                }
            });
            newDialog.show();
        }

        else if(view.getId()==R.id.save_btn){
            //save drawing
            AlertDialog.Builder saveDialog = new AlertDialog.Builder(this);
            saveDialog.setTitle("Save drawing");
            saveDialog.setMessage("Save drawing to device Gallery?");
            saveDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
                public void onClick(DialogInterface dialog, int which){
                    //save drawing
                    drawView.setDrawingCacheEnabled(true);
                    drawView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
                    Bitmap bitmap = drawView.getDrawingCache();
                    String path = Environment.getExternalStorageDirectory().getAbsolutePath();
                    File file = new File(path+File.separator+"Pictures"+File.separator+"image.png");
                    FileOutputStream ostream;
                    try {
                        file.createNewFile();
                        ostream = new FileOutputStream(file);
                        bitmap.compress(Bitmap.CompressFormat.PNG, 100, ostream);
                        ostream.flush();
                        ostream.close();
                        Toast.makeText(getApplicationContext(), "image saved :"+path, Toast.LENGTH_SHORT).show();


                    } catch (Exception e) {
                        e.printStackTrace();
                        Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_SHORT).show();
                    }
                    drawView.destroyDrawingCache();
                }
            });
            saveDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
                public void onClick(DialogInterface dialog, int which){
                    dialog.cancel();
                }
            });
            saveDialog.show();
        }

        if(view.getId()==R.id.next){
            bitArrayStore(i);
            drawView.startNew();
            i++;
        }
        if(view.getId() == R.id.prev){
            bitArrayStore(i);
            drawView.startNew();
            i--;
            drawView.redraw(bits, i);
        }

    }

    public void bitArrayStore(int k){

        drawView.buildDrawingCache();
        drawView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
        bits[k] = drawView.getDrawingCache();
        drawView.destroyDrawingCache();
    }

}

DrawingView.java DrawingView.java

public class DrawingView extends View {

    //drawing path
    private Path drawPath;
    //drawing and canvas paint
    private Paint drawPaint, canvasPaint;
    //initial color
    private int paintColor = 0xFF660000;
    //canvas
    private Canvas drawCanvas;
    //canvas bitmap
    private Bitmap canvasBitmap;
    private float brushSize, lastBrushSize;
    private boolean erase=false;

    public DrawingView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setupDrawing();
    }

    private void setupDrawing() {
//get drawing area setup for interaction
        brushSize = getResources().getInteger(R.integer.medium_size);
        lastBrushSize = brushSize;
        drawPath = new Path();
        drawPaint = new Paint();
        drawPaint.setColor(paintColor);
        drawPaint.setAntiAlias(true);
        drawPaint.setStrokeWidth(brushSize);
        drawPaint.setStyle(Paint.Style.STROKE);
        drawPaint.setStrokeJoin(Paint.Join.ROUND);
        drawPaint.setStrokeCap(Paint.Cap.ROUND);

        canvasPaint = new Paint(Paint.DITHER_FLAG);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//view given size
        super.onSizeChanged(w, h, oldw, oldh);
        canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        drawCanvas = new Canvas(canvasBitmap);
    }

    @Override
    protected void onDraw(Canvas canvas) {
//draw view
        canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
        canvas.drawPath(drawPath, drawPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
//detect user touch
        float touchX = event.getX();
        float touchY = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                drawPath.moveTo(touchX, touchY);
                break;
            case MotionEvent.ACTION_MOVE:
                drawPath.lineTo(touchX, touchY);
                break;
            case MotionEvent.ACTION_UP:
                drawCanvas.drawPath(drawPath, drawPaint);
                drawPath.reset();
                break;
            default:
                return false;
        }
        invalidate();
        return true;
    }

    public void setColor(String newColor) {
//set color
        invalidate();
        paintColor = Color.parseColor(newColor);
        drawPaint.setColor(paintColor);
    }

    public void setBrushSize(float newSize) {
//update sizefloat pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
        float pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                newSize, getResources().getDisplayMetrics());
        brushSize = pixelAmount;
        drawPaint.setStrokeWidth(brushSize);
    }
    public void setLastBrushSize(float lastSize){
        lastBrushSize=lastSize;
    }
    public float getLastBrushSize(){
        return lastBrushSize;
    }

    public void setErase(boolean isErase){
//set erase true or false
        erase=isErase;
        if(erase) drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        else drawPaint.setXfermode(null);
    }

    public void startNew(){
        drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
        invalidate();


//        Bitmap b= BitmapFactory.decodeFile("/storage/emulated/0/Pictures/image.png");
//        drawCanvas.drawBitmap(b, 0, 0, null);
//
//        invalidate();

    }


    public void redraw(Bitmap[] bits, int i) {
        drawCanvas.drawBitmap(bits[i], 0, 0, null);
        invalidate();
    }
}

Problem is when i click on Prev button the app is crashing. 问题是,当我单击“上一步”按钮时,应用程序崩溃了。 Can anyone please help me with this issue ?! 谁能帮我解决这个问题?

Instead of 代替

bits[k] = drawView.getDrawingCache();

in bitArrayStore() method bitArrayStore()方法中

It should be 它应该是

bits[k] = Bitmap.createBitmap(drawView.getDrawingCache());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM