Thread de UI do Android bloqueado em nova atividade
-
20-12-2019 - |
Pergunta
Estou trabalhando em um pequeno jogo Android que lida com o desenho de tela em um thread de trabalho.Após o término do jogo, esse thread deve iniciar a próxima atividade, mas de alguma forma o thread da UI parece ser bloqueado ao iniciar uma nova função.
Este é o Main-Loop dos meus jogos:
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));
}
A função performTick()
processa a lógica do jogo e retorna null
quando o jogo termina. draw()
faz a renderização.Ambas as funções funcionam perfeitamente - o problema é lose()
, que não faz nada além de iniciar uma nova 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);
}
});
}
Quando o jogo termina, a nova atividade (Menu Principal) inicia normalmente, mas não reage a nenhum evento de toque.Não há saída do LogCat e nenhuma exceção ocorre.Pior ainda, lose()
funciona normalmente quando é chamado ANTES do início do loop principal.
Estou trabalhando nisso há dias.Tentei iniciar a Activity diretamente do Thread de trabalho (sem usar um Handler
em lose()
) e pesquisei na Internet por horas - nada ajuda.Parece que o UI Thread está de alguma forma bloqueado ou preso em um loop infinito e não tenho ideia de como consertar isso.
Tudo é depurado em um dispositivo Nexus 4.
Por falar nisso: MainMenu.onCreate()
funciona normalmente quando iniciado de outra maneira.
Por favor me ajude, ma3o
Solução
Você não desbloqueia a tela quando a instrução if é verdadeira.O break vai tirar você do momento, deixando a tela travada.
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));
}
Você também deve desbloquear dentro da instrução if (antes ou depois de perder ()).
Outras dicas
Em vez disso, se While(true)
você pode ter While(myVar)
onde myVar
é um booleano que é verdadeiro enquanto o jogo deve estar em execução e definido como falso quando você chama lose()
No seu caso, você continuou a desenhar, embora não fosse necessário.