Neste exemplo mostro uma abordagem de separar a Thread em uma Classe separada com métodos para controlar o estado de execução da Thread, deixando o código mais limpo.
Crie uma classe ContadorHandle.class. Esta classe receberá o EditText onde será atualizado o contador.
public class ContadorHandle implements Runnable {
private TextView txtView;
private Handler handler;
private boolean running = false;
private int counter = 0;
private int interval=1000;
public ContadorHandle(TextView txtView) {
this.txtView = txtView;
handler = new Handler();
}
public int getInterval() {
return interval;
}
public void setInterval(int interval) {
this.interval = interval;
}
public void start() {
if (running == false) {
running = true;
handler.postDelayed(this, interval);
Log.i("LOG", "START");
} else{
Log.i("LOG", "ALREADY RUNNING");
}
}
public void resume(){
start();
}
public void restart(){
stop();
start();
}
public void stop() {
Log.i("LOG", "STOPPED");
running = false;
handler.removeCallbacks(this);
// No stop eu reinicio as variaveis
counter = 0;
txtView.setText("" + 0);
}
public void pause() {
Log.i("LOG", "PAUSED");
running = false;
handler.removeCallbacks(this);
} public boolean isRunning() {
return running;
}
@Override
public void run() {
counter++;
handler.postDelayed(this, interval);
txtView.setText("" + counter);
}
}
1) Instancie a classe
2) Configure o intervalo de tempo
3) Utilize os métodos para controlar o estado da Thread.
Exemplo de utilização na MainActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button startButton = (Button) findViewById(R.id.start_button);
final Button stopButton = (Button) findViewById(R.id.stop_button);
final TextView txtView = (TextView) findViewById(R.id.txtview);
// Instancia o contador com handle e passa o TextView que será atualizado
final ContadorHandle contador = new ContadorHandle(txtView);
// Configure o intervalo de execução
contador.setInterval(1000); // 1 segundo
// Se clicar no botão PAUSAR mudar o texto para CONTINUAR
startButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!contador.isRunning()) {
contador.start(); // Inicia ou continua a contagem
startButton.setText("PAUSAR");
} else {
contador.pause(); // Pausa a contagem
startButton.setText("CONTINUAR");
}
}
});
// Evento de clique do botão STOP
stopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
contador.stop(); // Para o contador (volta em zero)
startButton.setText("INICIAR");
}
});
}
Arquivo activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="@layout/activity_main">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="HANDLE"
android:id="@+id/textView" />
<TextView
android:id="@+id/txtview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="0"
android:textSize="30dp"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/start_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="INICIAR"/>
<Button
android:id="@+id/stop_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="PARAR"/>
</LinearLayout>
</LinearLayout>
Vídeo do contador:
A desvantagem desse exemplo é que utilizando Handler desta forma não oferece uma precisão muito boa, com o tempo é possível verificar que o contador começa atrasar a contagem de segundos. De qualquer forma, essa classe permite ser adaptada para outros fins onde não é necessário muita precisão, como por exemplo fazer a animação de uma figura.
Exemplo da classe ContadorHandle adaptada para girar uma figura:
public class RotateImageHandle implements Runnable {
private ImageView imageView;
private Handler handler;
private boolean running = false;
private float rotation = 0;
private int interval = 1;
public RotateImageHandle(ImageView imageView) {
this.imageView = imageView;
handler = new Handler();
}
public int getInterval() {
return interval;
}
public void setInterval(int interval) {
this.interval = interval;
}
public void start() {
if (running == false) {
running = true;
handler.postDelayed(this, interval);
Log.i("LOG", "START");
} else {
Log.i("LOG", "ALREADY RUNNING");
}
}
public void stop() {
Log.i("LOG", "STOP");
running = false;
handler.removeCallbacks(this);
// No stop eu reinicio as variaveis
rotation = 0;
imageView.setRotation(0);
}
public void pause() {
Log.i("LOG", "PAUSE");
running = false;
handler.removeCallbacks(this);
}
public boolean isRunning() {
return running;
}
@Override
public void run() {
rotation = rotation + 8;
handler.postDelayed(this, interval);
imageView.setRotation(rotation);
}
}
Esta classe funciona igual ao ContadorHandle, mas ao invés de receber um EditText recebe um ImageView, e começa a rotacionar a imagem com o método start.
Para criar um contador com maior precisão é necessário utilizar a classe TimerTask, que mostro no post a seguir.
Até mais.
Nenhum comentário:
Postar um comentário