Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Canvas object must be the same instance that was previously returned by lockCanvas

I have a custom SurfaceView with a method doDraw() that draws a background and a bitmap. The problem is when I run this I get an error

Caused by: java.lang.IllegalArgumentException: canvas object must be the same instance that was previously returned by lockCanvas

I don't see why this is happening. I don't declare any other canvases anywhere else in my code. I only have two other classes, MainActivity and SurfaceViewExample. MainActivity just has an intent to open SurfaceViewExample, and SurfaceViewExample just has a method called by some buttons.

OurView class:

package com.thatoneprogrammerkid.gameminimum;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class OurView extends SurfaceView implements SurfaceHolder.Callback {

    private SurfaceHolder holder;
    private Bitmap testimg;
    public int xCoord = 500;
    public int yCoord = 500;

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

    public OurView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public OurView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        holder = getHolder();
        holder.addCallback(this);
        testimg = BitmapFactory.decodeResource(getResources(),R.drawable.testimg);
    }

    void moveImage(int xChange, int yChange) {
        xCoord += xChange;
        yCoord += yChange;
        doDraw();
    }

    void doDraw() {
        Canvas myCanvas = holder.lockCanvas();
        if (myCanvas != null) {
            myCanvas.drawARGB(255, 55, 255, 255);
            myCanvas.drawBitmap(testimg, xCoord, yCoord, null);
        }
        holder.unlockCanvasAndPost(myCanvas);
    }

    @Override
    public void surfaceCreated(final SurfaceHolder holder) {
        doDraw();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}


    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {}

}
like image 792
WD40 Avatar asked Feb 10 '23 07:02

WD40


1 Answers

Move the unlockCanvasAndPost() inside the if (myCanvas != null) { statement. My guess is lockCanvas() is returning null, and you're attempting to unlock a null reference.

Looking at the source code, the test for "is it the same" comes before the test for "is it locked at all" -- and mCanvas is initialized to a non-null value.

like image 101
fadden Avatar answered Feb 13 '23 06:02

fadden