1

I'm trying to make an Android game, and I am following a few code samples to get my game loop working. It involves making a new thread. In the run() method I have a try/finally block. After the finally block executes a NullPointerException is thrown. I have no idea why, nothing seems to be null and even if it is, nothing is referencing anything null. I thought maybe this was null but it doesn't seem to be. Here's the code I think is relevant:

public class MainThread extends Thread {
private boolean running;
private final SurfaceHolder holder;

private boolean GameIsRunning = false;

private int mMode;
public static final int STATE_LOSE = 1;
public static final int STATE_PAUSE = 2;
public static final int STATE_READY = 3;
public static final int STATE_RUNNING = 4;
public static final int STATE_WIN = 5;

private MainGame game;

public MainThread(SurfaceHolder holder, MainGamePanel panel) {
    super();
    this.holder = holder;
    game = new MainGame(panel.getContext());
    mMode = STATE_RUNNING;
}

@Override
public void run() {
    while (running) {
        Canvas c = null;
        try {
            c = holder.lockCanvas(null);
            synchronized (holder) {
                if (mMode == STATE_RUNNING) {
                    updateAll();
                }
                drawAll(c);
            }
        } finally {
            // do this in a finally so that if an exception is thrown
            // during the above, we don't leave the Surface in an
            // inconsistent state
            if (c != null) {
                holder.unlockCanvasAndPost(c);
            }
        } // <<<<<<<<<<<<< After this line executes a null pointer exception is thrown
    } 
}

Creation of thread:

public class MainGamePanel extends SurfaceView implements SurfaceHolder.Callback{

private MainThread thread;

public MainGamePanel(Context context) {
    super(context);
    getHolder().addCallback(this);

    // create the game loop thread
    thread = new MainThread(getHolder(), this);
    setFocusable(true);
}


@Override
public void surfaceCreated(SurfaceHolder holder) {
    thread.setRunning(true);
    thread.start();
}

Thanks!

robev
  • 1,909
  • 3
  • 23
  • 32

2 Answers2

4

The NPE is thrown inside the try block and becomes visible after the finally block has been executed.

From looking at the code, it happens most likely because c is null when you pass it to updateAll. You have a null check inside the finally block - so I guess you expect that it may be null. Add another check in the try block and handle c == null there too.


From the android API (SurfaceHolder#lockCanvas):

A null is returned if the surface has not been created or otherwise cannot be edited

Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
-1

Try replacing c = holder.lockCanvas(null); with c = holder.lockCanvas();

And of course you should post your stacktrace.

Egor
  • 39,695
  • 10
  • 113
  • 130
  • Stack trace was useless that's why i didn't post it: Thread [<17> Thread-9] (Suspended (exception NullPointerException)) MainThread.run() line: 52 – robev May 27 '11 at 08:02
  • @robev, stacktraces are never useless, you just have to know how to read the. Even a stacktrace with debug symbols turned off (no line numbers) indicate what the method call stack is which tends to narrow down the possible problem areas significantly. – Tim Bender May 27 '11 at 19:17