我为自己打了一场平庸的比赛。它有一个主菜单活动,当你点击播放开始一个新的游戏活动。当您输掉游戏时,您可以重试或返回主菜单。游戏活动的后退按钮只是这个编码的一个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和一个重复的问题。但我不明白为什么当我切换到我的主菜单活动时,它会导致此错误,当游戏面板甚至没有链接到主菜单活动。请帮助一个年轻的学生:)谢谢你,如果你想看到任何其他代码,我会立即编辑这篇文章。
答案 0 :(得分:0)
在开始另一个活动之前,检查负责调用draw
方法的线程是否仍在运行。我不太确定,但它可能仍然试图在SurfaceView上渲染,即使它已经从窗口中分离出来。
修改强>
我能够复制你的问题。处理绘图的线程并不总是立即获得您用作while循环条件的变量的更新值。您可以选择执行同步和/或其他线程,但您可以尝试打破while循环,就像我在下面的代码中所做的那样。另外,尝试通过在SurfaceHolder.Callback#surfaceDestroyed(SurfaceHolder)
。
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;
}
}
}
}
}