Search code examples
androidmultithreadingui-threadblocked

Android UI Thread blocked in new Activity


I'm working on a small Android game that handles canvas drawing on a working thread. After the game is over this thread should start the next activity, but somehow the UI thread seems to get blocked by starting a new function.

This is my games Main-Loop:

while(true)
    // Perform Ticks until the player makes a mistake
    c = _surfaceHolder.lockCanvas();
    if ((toDraw = rh.performTick()) == null) {
         lose();
         break;
     }
     _surfaceHolder.unlockCanvasAndPost(draw(toDraw,c));
}

The function performTick() processes the game logic and returns null when the game ends. draw()does the rendering. Both Functions work perfect - the problem is lose(), which does nothing than starting a new Activity:

    protected void lose() {
        Handler handler = new Handler(Looper.getMainLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                Intent intent = new Intent(_context, MainMenu.class);
                _context.startActivity(intent);
            }
        });
    }

When the Game ends, the new Activiy (MainMenu) starts normally but does not react on any touch events. There is no LogCat output and no Exception occuring. Even worse, lose()works normal when its called BEFORE the main loop starts.

I've been working on this for days now. I tried to start the Activity directly from the working Thread (without using a Handler in lose()) and searched the Internet for hours - nothing helps. It seems like the UI Thread is somehow blocked or caught in an infinite loop, and i have no idea how to fix this.

Everything is debugged on a Nexus 4 device.

Btw: MainMenu.onCreate() works normal when started another way.

Please help, MA3o


Solution

  • You don't unlock the canvas when the if statement is true. Break will get you out of the while, leaving the canvas locked.

    while(true)
        // Perform Ticks until the player makes a mistake
        c = _surfaceHolder.lockCanvas();
        if ((toDraw = rh.performTick()) == null) {
             lose();
             break;
         }
    
         // this line won't be executed whether the if statement above is true
         _surfaceHolder.unlockCanvasAndPost(draw(toDraw,c));
    }
    

    You should unlock inside the if statement also (before or after lose()).