Tutorial Android #8 – Barras de Progresso

Padrão

Olá pessoal! Neste tutorial vamos simular a execução de uma tarefa em background, atualizando a interface do usuário através de uma barra de progresso. Neste ponto, a aplicação Lista de Restaurantes ainda não tem nenhuma tarefa que demande processamento maciço que justifique tal uso, de forma que este tutorial serve apenas para exemplificar o uso de threads e barras de progresso.

Para começar, em vez de utilizar o widget ProgressBar, vamos utilizar a funcionalidade de barra de progresso da própria Activity. Isso fará com que a barra de progresso apareça junto com o título, fazendo com que não precisemos nos preocupar em encaixá-la no layout. Para que isso aconteça, precisamos adicionar uma linha ao método onCreate(), chamando o método antes do setContentView(). Dessa forma, nosso método onCreate() fica assim:

@Override
public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	requestWindowFeature(Window.FEATURE_PROGRESS);
	setContentView(R.layout.main);
	...

Além disso, vamos adicionar um novo atributo à classe, do tipo int, chamado progresso.

EditText nome = null;
EditText endereco = null;
EditText anotacoes = null;
RadioGroup tipos = null;
int progresso;

Continuando, precisamos de um método que faça alguma coisa, pra utilizar a barra de progresso. Para isso, vamos criar o método fazerAlgoDemorado() dentro da classe ListaRestaurantes.

private void fazerAlgoDemorado(final int incremento) {
	SystemClock.sleep(250); // Pode ser algo mais útil!
}

O próximo passo é criar um Runnable na classe ListaRestaurantes que execute fazerAlgoDemorado() algumas vezes. Fica assim:

private Runnable tarefaLonga = new Runnable() {
	public void run() {
		for (int i = 0; i < 20; i++) {
			fazerAlgoDemorado(500);
		}
	}
};

Com os ciclos executados na tarefaLonga, a duração total será de 5s com 20 execuções.

O próximo passo é ajustarmos alguma forma de disparar essa falsa tarefa em algum ponto. O jeito mais fácil de fazermos isso é adicionando uma opção ao menu, de forma que o usuário possa abrir o menu e selecioná-la. O arquivo de imagem tarefa.png encontra-se junto com o projeto no final do post. Atualize, então, o arquivo opcao.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
	<item android:id="@+id/anotacao"
	    android:title="Exibir Anotação"
	    android:icon="@drawable/anotacao"/>
	<item android:id="@+id/rodar"
	    android:title="Executar Tarefa"
	    android:icon="@drawable/tarefa"/>
</menu>

Continuando, precisamos vincular a funcionalidade a nossa nova opção do menu. Dessa forma, atualize o método onOptionsItemSelected():

@Override
public boolean onOptionsItemSelected(MenuItem item) {
	if (item.getItemId() == R.id.anotacao) {
		String mensagem = "Nenhum restaurante selecionado";

		if (atual != null) {
			mensagem = atual.getAnotacoes();
		}

		Toast.makeText(this, mensagem, Toast.LENGTH_LONG).show();

		return true;
	} else if (item.getItemId() == R.id.rodar) {
		new Thread(tarefaLonga).start();
	}

	return super.onOptionsItemSelected(item);
}

Caso você execute a aplicação neste momento, ainda não será possível ver a barra de progresso funcionando, mas já será possível conferir a nova opção em nosso menu:

Agora vamos, de fato, gerenciar a nossa barra de progresso. Primeiramente, atualize o método onOptionsItemSelected() para tornar a barra visível e inicializá-la:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
	if (item.getItemId() == R.id.anotacao) {
		String mensagem = "Nenhum restaurante selecionado";

		if (atual != null) {
			mensagem = atual.getAnotacoes();
		}

		Toast.makeText(this, mensagem, Toast.LENGTH_LONG).show();

		return true;
	} else if (item.getItemId() == R.id.rodar) {
		setProgressBarVisibility(true);
		progresso = 0;
		new Thread(tarefaLonga).start();

		return true;
	}

	return super.onOptionsItemSelected(item);
}

Agora, atualize o método fazerAlgoDemorado() para que atualize o status da barra a cada passagem por ele:

private void fazerAlgoDemorado(final int incremento) {
	runOnUiThread(new Runnable() {
		public void run() {
			progresso += incremento;
			setProgress(progresso);
		}
	});

	SystemClock.sleep(250); // Pode ser algo mais útil!
}

Por fim, precisamos ocultar a barra de progresso quando a tarefa for completada. Atualize, então, nossa tarefaLonga:

private Runnable tarefaLonga = new Runnable() {
	public void run() {
		for (int i = 0; i < 20; i++) {
			fazerAlgoDemorado(500);
		}

		runOnUiThread(new Runnable() {
			public void run() {
				setProgressBarVisibility(false);
			}
		});
	}
};

Pronto! Agora já temos uma barra de progresso que sinaliza o progresso da execução de uma enrolação tarefa.

Se você perdeu alguma coisa ou quiser baixar o projeto, é só clicar aqui.

Até a próxima! 🙂