Síncrono x Assíncrono
Quem está acompanhando esta série de posts já deve estar cansando das minhas menções ao assincronismo na programação para Android. No Android nunca o seu código fica parado no meio de um método aguardando uma interação do usuário. Existem bons motivos para isto, mas é particularmente chato nestas interações simples.
A Microsoft resolve isto no Windows através das funções DialogBox e MessageBox. Estas funções possuem internamente um "message loop" para tratar as interações que ocorrem durante a espera. Não é uma solução exatamente limpa, mas permite coisas extremamente simples como:
if (MessageBox (hDlg, "Anexar detalhes?", szAppName, MB_YESNO | MB_ICONQUESTION) == IDYES) { AnexaDetalhes(); } EnviaMensagem ();A execução deste trecho pára aguardando o operador selecionar Sim ou Não e depois continua normalmente.
No Android não dá para fazer isto. O que gera bastante discussão. E é claro que alguém achou uma forma de fazer usando APIs internas (não recomendo usar este código!).
The Android Way
Como no Windows, um dialog no Android é uma janela que normalmente não ocupa toda a tela e é usada para o operador tomar uma decisão ou fornecer uma informação necessária para continuar a execução de uma tarefa. A classe Dialog é a classe base para as classes que implementam dialogs; ao invés de ser instanciada diretamente deve ser utilizada uma das classes derivadas. AlertDialog é a mais comum delas.
AlertDialog é uma classe bastante flexível em termos do conteúdo da janela apresentada. A janela é composta por três partes:
- Um título (opcional).
- O conteúdo, que pode ser uma mensagem, uma lista ou (com um pouco mais de trabalho) qualquer coisa.
- Os botões de seleção, que podem ser até três.
AlertDialog.Builder builder = new AlertDialog.Builder(TesteAlertActivity.this); builder.setTitle(R.string.app_name); builder.setMessage(R.string.msg_confirma); builder.setPositiveButton(R.string.sim, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { AnexaDetalhes(); EnviaMensagem(); } }); builder.setNegativeButton(R.string.nao, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { EnviaMensagem(); } }); AlertDialog dialog = builder.create(); dialog.show();O mais importante nisto tudo é entender que a execução não para em dialog.show(). Você só vai saber o que o operador decidiu quando um dos event listeners for chamado. No caso isto obrigou a ter duas chamadas separadas a EnviaMensagem, uma em cada listener.
Para confundir um pouco mais, é comum aproveitar o fato dos métodos de AlertDialog,Builder retornarem um referência ao próprio objeto para compactar um pouco mais o código:
final AlertDialog dialog = new AlertDialog.Builder(TesteAlertActivity.this) .setTitle(R.string.app_name) .setMessage(R.string.msg_confirma) .setPositiveButton(R.string.sim, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { AnexaDetalhes(); EnviaMensagem(); } }) .setNegativeButton(R.string.nao, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { EnviaMensagem(); } }) .create(); dialog.show();
É claro que existem bons motivos para escrever tudo isto ao invés de um simples MessageBox, mas bem que o pessoal da Google podia pelo menos manifestar alguma simpatia pelos programadores ao invés de responderem secamente "você não quer fazer isto, faça do jeito certo - o meu".
2 comentários:
Olá! Ficou faltando a versão Android do código para windows (o 2º bloco de código está vazio). OU é o bloco que aparece logo em seguida (o 3º), o que faz bastante sentido pelo contexto. ;-)
Acertado... o editor do blogger não é exatamente um WYSIWYG e para entrar com o código precisa mudar para o modo HTML; eu acabei me confundindo e esqueci de conferir o preview. Obrigado pelo aviso!
Postar um comentário