web-dev-qa-db-fra.com

Android: compteur de temps simple

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)
21
DavidNg

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();
 }
36
Pavel Dudka

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.

6
hovanessyan

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();
}
3
Giedrius Šlikas

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.

2
Andy

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();
}
0