52 votes

Minuterie Android mettant à jour une vue textuelle (UI)

J'utilise une minuterie pour créer un chronomètre. La minuterie fonctionne en augmentant une valeur entière. Je souhaite ensuite afficher cette valeur dans l'activité en mettant constamment à jour un textview.

Voici mon code du service où j'essaie de mettre à jour le textview de l'activité :

 protected static void startTimer() {
    isTimerRunning = true; 
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            elapsedTime += 1; //increase every sec
            StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview
        }
    }, 0, 1000);
}

J'ai eu une sorte d'erreur concernant la mise à jour de l'interface utilisateur dans le mauvais fil.

Comment puis-je adapter mon code pour accomplir cette tâche de mise à jour constante de la vue textuelle ?

92voto

Nirav Points 1669
protected static void startTimer() {
    isTimerRunning = true; 
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            elapsedTime += 1; //increase every sec
            mHandler.obtainMessage(1).sendToTarget();
        }
    }, 0, 1000);
}

public Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {
        StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview
    }
};

Le code ci-dessus fonctionnera...

Remarque : Les gestionnaires doivent être créés dans votre thread principal afin que vous puissiez modifier le contenu de l'interface utilisateur.

8voto

inazaruk Points 37760

Vous devriez Handler pour mettre à jour l'interface utilisateur toutes les X secondes. Voici une autre question qui montre un exemple : répéter une tâche avec un délai ?

Votre approche ne fonctionne pas car vous essayez de mettre à jour l'interface utilisateur à partir d'un thread non-UI. Ce n'est pas autorisé.

6voto

DongXu Points 152
StopWatch.time.post(new Runnable() {
    StopWatch.time.setText(formatIntoHHMMSS(elapsedTime));
});

ce bloc de code est basé sur Handler mais vous n'avez pas besoin de créer votre propre instance de Handler.

2voto

Pyrodante Points 2621

TimerTask implémente Runnable, ce qui en ferait un thread. Vous ne pouvez pas mettre à jour le fil principal de l'interface utilisateur directement à partir d'un fil différent sans travail. Une chose que vous pouvez faire est d'utiliser la tâche asynchrone pour créer le minuteur et publier une mise à jour toutes les secondes qui mettra à jour l'interface utilisateur.

2voto

John Leehey Points 10405

Je suppose que StopWatch.time est une référence statique ou publique à votre TextView. Au lieu de faire cela, vous devez implémenter un BroadcastReceiver pour communiquer entre votre minuteur (qui s'exécute à partir d'un thread séparé) et votre TextView.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X