Android应用程序冻结活动开关

时间:2017-03-29 20:02:19

标签: java android

我为自己打了一场平庸的比赛。它有一个主菜单活动,当你点击播放开始一个新的游戏活动。当您输掉游戏时,您可以重试或返回主菜单。游戏活动的后退按钮只是这个编码的一个ractangle。

if (GlobalVariables.GAMEOVER && backButton.contains((int)(event.getX()), (int)(event.getY())))
            {
                Intent backButtonIntent = new Intent(context, MainMenuActivity.class);
                context.startActivity(backButtonIntent);
            }

程序不会崩溃,它会切换到主菜单活动,但它被冻结,没有按钮可点击。这是我得到的错误。

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:451)
 at android.view.View.draw(View.java:17472)
 at android.view.SurfaceView.draw(SurfaceView.java:442)
 at com.example.jordanschanzenbach.myapplication.GamePanel.draw(GamePanel.java:84)
 at com.example.jordanschanzenbach.myapplication.MainThread.run(MainThread.java:52)

这是它在游戏面板中指向的代码。 " super.draw(帆布)"

public void draw(Canvas canvas)
{
    super.draw(canvas);
    backGround.draw(canvas);
    gameFloor.draw(canvas);
    gamePlayScene.draw(canvas);
}

我知道这是一个nullpointerexception和一个重复的问题。但我不明白为什么当我切换到我的主菜单活动时,它会导致此错误,当游戏面板甚至没有链接到主菜单活动。请帮助一个年轻的学生:)谢谢你,如果你想看到任何其他代码,我会立即编辑这篇文章。

1 个答案:

答案 0 :(得分:0)

在开始另一个活动之前,检查负责调用draw方法的线程是否仍在运行。我不太确定,但它可能仍然试图在SurfaceView上渲染,即使它已经从窗口中分离出来。

修改

我能够复制你的问题。处理绘图的线程并不总是立即获得您用作while循环条件的变量的更新值。您可以选择执行同步和/或其他线程,但您可以尝试打破while循环,就像我在下面的代码中所做的那样。另外,尝试通过在SurfaceHolder.Callback#surfaceDestroyed(SurfaceHolder)

中使while循环条件为false来停止绘制线程
public class GamePanel extends SurfaceView implements SurfaceHolder.Callback {
    private TextPaint paint;
    private volatile boolean isDrawing;
    private DrawingThread drawingThread;

    public GamePanel(Context context) {
        super(context);
        initialize();
    }

    // omitted the other constructors for brevity

    private void initialize() {
        ...
        drawingThread = new DrawingThread();

        // do this so that you can get an surface updates
        getHolder().addCallback(this);
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);

        canvas.drawText("Hello, world", 20, 20, paint);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        isDrawing = true;
        drawingThread.start(); 
        // start drawing only after the surface was created
    }

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

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        isDrawing = false; 
        // try to stop the drawing thread when the surface
        // is destroyed
    }

    private class DrawingThread extends Thread {
        @Override
        public void run() {
            while (isDrawing) {
                try {
                    Canvas canvas = getHolder().lockCanvas();
                    // check if canvas is null just to make sure
                    if (canvas == null) break;
                    draw(canvas);
                    getHolder().unlockCanvasAndPost(canvas);
                } catch (IllegalArgumentException e) {
                    // This is thrown by SurfaceHolder#lockCanvas().
                    // Break when the surface has already been destroyed 
                    // but the variable `isDrawing` is still true.
                    break;
                }
            }
        }
    }
}