SurfaceHolder.lockCanvas () Returns null Even though it was available

I have an Android game on the market and I get NullPointers crash reports when I try to use the canvas. I can assume this because it SurfaceHolder.lockCanvas()returns null, however it does this average gameplay, because depending on where it crashes, it SurfaceHolder.lockCanvas()returned a valid canvas at least once.

This is difficult to debug because I cannot recreate it on my own device, which makes me wonder if this is related to specific devices. The only hint I have is that one of the devices on which this happened was the Nexus 7.

NOTE. This is not the same problem as a question with a similar name. Another question was trying to use the canvas before it was available, while it was available.

Below is a sample of my code:

public class GameView extends SurfaceView implements SurfaceHolder.Callback
{
    class GameThread extends Thread
    {
        @Override
        public void run()
        {
            while (running)
            {
                Canvas c = null;
                try
                {
                    c = mSurfaceHolder.lockCanvas();

                    synchronized (mSurfaceHolder)
                    {
                        long start = System.currentTimeMillis();
                        doDraw(c);
                        long diff = System.currentTimeMillis() - start;

                        if (diff < frameRate)
                            Thread.sleep(frameRate - diff);
                    }
                } catch (InterruptedException e)
                {
                }
                finally
                {
                    if (c != null)
                    {
                        mSurfaceHolder.unlockCanvasAndPost(c);
                    }
                }
            }
        }
    }

    public void surfaceCreated(SurfaceHolder holder)
    {
        if (gThread.getState() == Thread.State.TERMINATED)
        {
            gThread = new GameThread(getHolder(), getContext(), getHandler());
            gThread.start();
        }
        else
        {
            gThread.start();
        }
    }
}
+5
source share
1 answer

I also ran into this problem. This happens sporadically when the surface is already destroyed (and has already been specified surfaceDestroyed), but the looper flow is already inside the while loop (and after checking the variable running). Then lockCanvasreturns null (as the surface collapses). This can happen, for example, when the screen orientation changes or the activity changes. This is a β€œsimple” problem with threading race conditions.

if (canvas == null) continue; lockCanvas ( ). running , .

0

All Articles