由于锁定画布的错误而导致重新启动游戏活动时出错

时间:2018-08-17 22:07:24

标签: android surfaceview

我正在创建2D游戏,并且使用线程和SurfaceView来运行游戏。游戏运行平稳,但是当我重新启动游戏活动时,使用startActivity(intent)屏幕变黑,并且一遍又一遍地收到以下错误消息。

错误消息:

08-17 20:50:57.144 13366-13426/com.my.app W/System.err: java.lang.IllegalArgumentException: canvas object must be the same instance that was previously returned by lockCanvas
        at android.view.Surface.unlockSwCanvasAndPost(Surface.java:370)
        at android.view.Surface.unlockCanvasAndPost(Surface.java:363)
08-17 20:50:57.145 13366-13426/com.my.app W/System.err:     at android.view.SurfaceView$3.unlockCanvasAndPost(SurfaceView.java:1089)
08-17 20:50:57.148 13366-13426/com.my.app W/System.err:     at com.my.app.MainThread.run(MainThread.java:65)
08-17 20:50:57.149 13366-13426/com.my.app E/SurfaceHolder: Exception locking surface
    java.lang.IllegalArgumentException: Surface was already locked
        at android.view.Surface.lockCanvas(Surface.java:343)
        at android.view.SurfaceView$3.internalLockCanvas(SurfaceView.java:1050)
        at android.view.SurfaceView$3.lockCanvas(SurfaceView.java:1010)
        at com.my.app.MainThread.run(MainThread.java:54)
08-17 20:50:57.168 13366-13447/com.my.app E/SurfaceHolder: Exception locking surface
    java.lang.IllegalArgumentException: Surface was already locked
        at android.view.Surface.lockCanvas(Surface.java:343)
        at android.view.SurfaceView$3.internalLockCanvas(SurfaceView.java:1050)
        at android.view.SurfaceView$3.lockCanvas(SurfaceView.java:1010)
        at com.my.app.MainThread.run(MainThread.java:54)
08-17 20:50:57.219 13366-13426/com.my.app W/System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Canvas.drawColor(int, android.graphics.PorterDuff$Mode)' on a null object reference
        at android.view.SurfaceView.dispatchDraw(SurfaceView.java:394)
        at android.view.View.draw(View.java:20210)
        at android.view.SurfaceView.draw(SurfaceView.java:385)
08-17 20:50:57.220 13366-13426/com.my.app W/System.err:     at com.my.app.GameView.draw(GameActivity.java:166)
        at com.my.app.MainThread.run(MainThread.java:57)

我的运行循环中的线程代码:

@Override
public void run() {
    long starttime;
    long timeMillis = 1000 / MAX_FPS;
    long waitTime;
    int frameCount = 0;
    long totalTime = 0;
    long targetTime = 1000 / MAX_FPS;

    while(running) {
        nanotime = System.nanoTime();
        millitime = nanotime / 1000000;

        starttime = nanotime;
        //Log.d(TAG, "Millitime: " + millitime + ", Nanotime: " + nanotime);

        canvas = null;

        try {
            canvas = this.surfaceHolder.lockCanvas();
            synchronized (surfaceHolder) {
                this.gameView.update(millitime);
                this.gameView.draw(canvas);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            if(canvas != null) {
                try {
                    surfaceHolder.unlockCanvasAndPost(canvas);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        timeMillis = (System.nanoTime() - starttime) / 1000000;
        waitTime = targetTime - timeMillis;
        //Log.d(TAG, "waitTime: " + waitTime + ", targetTime: " + targetTime + ", timeMillis: " + timeMillis);
        try {
            if (waitTime > 0){
                sleep(waitTime);
            }
        } catch (Exception e){
            e.printStackTrace();
        }

        totalTime += System.nanoTime() - starttime;
        frameCount++;
        if(frameCount == MAX_FPS){
            avrageFPS = (short) (1000 / ((totalTime / frameCount) / 1000000));
        }
    }
}

我的游戏活动的一部分:

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    if(thread.getRunning())
        close("surfaceDestroyed()");
}

public static void close(String caller) {
    Log.d(TAG + ":close()", caller);
    boolean retry = true;
    while (retry) {
        Log.d(TAG, "DONE!");
        try {
            thread.setRunning(false);
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
            Log.d(TAG, "FAIL!");
        }
        retry = false;
    }
}

如果您需要更多详细信息或更多代码,请随时提问,并请指定所需内容。谢谢!

1 个答案:

答案 0 :(得分:0)

尝试从运行循环线程代码中删除“ finally”块。而是在编辑画布后将其添加到try块中。您的线程类如下所示:

@Override
public void run() {
long starttime;
long timeMillis = 1000 / MAX_FPS;
long waitTime;
int frameCount = 0;
long totalTime = 0;
long targetTime = 1000 / MAX_FPS;

while(running) {
    nanotime = System.nanoTime();
    millitime = nanotime / 1000000;

    starttime = nanotime;
    //Log.d(TAG, "Millitime: " + millitime + ", Nanotime: " + nanotime);

    canvas = null;

    try {
        canvas = this.surfaceHolder.lockCanvas();
        synchronized (surfaceHolder) {
            this.gameView.update(millitime);
            this.gameView.draw(canvas);
        }
        if (canvas != null) {
            surfaceHolder.unlockCanvasAndPost(canvas);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    timeMillis = (System.nanoTime() - starttime) / 1000000;
    waitTime = targetTime - timeMillis;
    //Log.d(TAG, "waitTime: " + waitTime + ", targetTime: " + targetTime + ", timeMillis: " + timeMillis);
    try {
        if (waitTime > 0){
            sleep(waitTime);
        }
    } catch (Exception e){
        e.printStackTrace();
    }

    totalTime += System.nanoTime() - starttime;
    frameCount++;
    if(frameCount == MAX_FPS){
        avrageFPS = (short) (1000 / ((totalTime / frameCount) / 1000000));
    }
}
}