J'ai un programme simple avec un TextView et deux boutons: Button1 et Button2.
Cliquer sur le bouton 1 lancera un compteur, augmentant de 1 toutes les 1 secondes et affichera le résultat sur TextView; tinter le bouton 2 l'arrêtera. Voici une partie de mon code pour Button1. Mais ça ne marche pas.
Timer T=new Timer();
T.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
myTextView.setText("count="+count);
count++;
}
}, 1000, 1000);
Je sais qu'il y a des questions similaires à ce sujet en utilisant Thread mais il semble qu'ils ne mentionnent pas l'arrêt du compteur.
Toute suggestion est vraiment appréciée.
ajouté:
Bonjour, je viens de raccourcir mon code juste pour cela à partir d'un programme beaucoup plus gros, mais il est toujours bloqué:
package com.example.hello;
import Java.util.Timer;
import Java.util.TimerTask;
import Android.os.Bundle;
import Android.app.Activity;
import Android.view.Menu;
import Android.widget.TextView;
public class MainActivity extends Activity {
TextView myTextView;
int count=0;
Timer T;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myTextView=(TextView)findViewById(R.id.t);
T=new Timer();
T.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
myTextView.setText("count="+count);
count++;
}
}, 1000, 1000);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
Le fichier journal (je ne veux pas poster ceci car il est trop long mais quelqu'un l'a demandé):
07-28 17:35:07.012: W/dalvikvm(11331): threadid=7: thread exiting with uncaught exception (group=0x4001d800)
07-28 17:35:07.016: E/AndroidRuntime(11331): FATAL EXCEPTION: Timer-0
07-28 17:35:07.016: E/AndroidRuntime(11331): Android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
07-28 17:35:07.016: E/AndroidRuntime(11331): at Android.view.ViewRoot.checkThread(ViewRoot.Java:2802)
07-28 17:35:07.016: E/AndroidRuntime(11331): at Android.view.ViewRoot.requestLayout(ViewRoot.Java:594)
07-28 17:35:07.016: E/AndroidRuntime(11331): at Android.view.View.requestLayout(View.Java:8125)
07-28 17:35:07.016: E/AndroidRuntime(11331): at Android.view.View.requestLayout(View.Java:8125)
07-28 17:35:07.016: E/AndroidRuntime(11331): at Android.view.View.requestLayout(View.Java:8125)
07-28 17:35:07.016: E/AndroidRuntime(11331): at Android.view.View.requestLayout(View.Java:8125)
07-28 17:35:07.016: E/AndroidRuntime(11331): at Android.widget.RelativeLayout.requestLayout(RelativeLayout.Java:254)
07-28 17:35:07.016: E/AndroidRuntime(11331): at Android.view.View.requestLayout(View.Java:8125)
07-28 17:35:07.016: E/AndroidRuntime(11331): at Android.widget.TextView.checkForRelayout(TextView.Java:5378)
07-28 17:35:07.016: E/AndroidRuntime(11331): at Android.widget.TextView.setText(TextView.Java:2688)
07-28 17:35:07.016: E/AndroidRuntime(11331): at Android.widget.TextView.setText(TextView.Java:2556)
07-28 17:35:07.016: E/AndroidRuntime(11331): at Android.widget.TextView.setText(TextView.Java:2531)
07-28 17:35:07.016: E/AndroidRuntime(11331): at com.example.hello.MainActivity$1.run(MainActivity.Java:21)
07-28 17:35:07.016: E/AndroidRuntime(11331): at Java.util.Timer$TimerImpl.run(Timer.Java:289)
Vous pouvez introduire le drapeau. Quelque chose comme isPaused
. Déclenchez ce drapeau chaque fois que vous appuyez sur le bouton "Pause". Vérifiez la valeur de l'indicateur dans votre tâche de minuterie. Succès.
Timer T=new Timer();
T.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable()
{
@Override
public void run()
{
myTextView.setText("count="+count);
count++;
}
});
}
}, 1000, 1000);
onClick(View v)
{
//this is 'Pause' button click listener
T.cancel();
}
Chekout this exemple, qui utilise la classe Chronometer : http://Android-er.blogspot.com/2010/06/Android-chronometer.html
L'utilisation de la classe Chronometer vous évitera de gérer le thread vous-même.
Solution parfaite si vous souhaitez afficher l'horloge en cours d'exécution.
private void startClock(){
Thread t = new Thread() {
@Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
@Override
public void run() {
Calendar c = Calendar.getInstance();
int hours = c.get(Calendar.HOUR_OF_DAY);
int minutes = c.get(Calendar.MINUTE);
int seconds = c.get(Calendar.SECOND);
String curTime = String.format("%02d %02d %02d", hours, minutes, seconds);
clock.setText(curTime); //change clock to your textview
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
}
Pavel est sur la bonne voie pour l'arrêter, sauf que sa réponse est un gaspillage car cela n'arrête pas le chronomètre. Faites cela sur la partie qu'il a publiée avec la déclaration else ajoutée:
if(!isPaused)
{
myTextView.setText("count="+count);
count++;
} else {
cancel();//adding this makes it actually stop
}
Oh et tu as dit que ça s'est écrasé. Nous n'avons aucune idée de la raison pour laquelle il se bloque, donc malheureusement nous ne pouvons pas vraiment comprendre pourquoi il le fait à moins que nous voyions plus de code et l'erreur.
Good catch @yorkw Le problème est évidemment avec quelque chose qu'il essaie de faire quand il commence à fonctionner. Depuis son dit "Timer-0", cela signifie qu'il ne démarre jamais officiellement et qu'il est coincé dans cette partie. Première règle de l'exécution des threads, NE JAMAIS CHANGER LES ÉLÉMENTS DE L'UI DEHORS DE L'UI . Je suggère d'utiliser runOnUiThread
comme l'a dit york. Voici un lien sur la façon de l'utiliser: runOnUiThread . Je suis sûr que TimerTask
est un exécutable, ce qui signifie qu'il s'exécute sur un thread séparé. C'est moins ce que j'ai remarqué sur les documents.
De cette façon, c'est beaucoup plus simple. C'est une fonctionnalité mise à disposition sur le Android. Lien
public void initCountDownTimer(int time) {
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
textView.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
textView.setText("done!");
}
}.start();
}