web-dev-qa-db-fra.com

La mise à jour de l'interface utilisateur avec Runnable et postDelayed ne fonctionne pas avec l'application du minuteur

J'ai examiné chaque discussion et fil que je peux trouver pour que cela fonctionne, mais ce n'est pas le cas. J'ai une minuterie simple qui met à jour une vue de texte (mTimeTextField dans l'exemple ci-dessous). La méthode d'exécution mUpdateTimeTask est exécutée correctement (toutes les secondes) mais le champ UI/texte n'est pas mis à jour.

J'ai un code basé sur les informations trouvées ici:

http://Android-developers.blogspot.com/2007/11/stitch-in-time.htmlhttp://developer.Android.com/resources/articles/timed-ui- updates.html

Voici le code:

package com.something.handlertest;

import com.something.handlertest.R;

import Android.app.Activity;
import Android.content.Intent;
import Android.os.Bundle;
import Android.os.Handler;
import Android.os.SystemClock;
import Android.view.View;
import Android.widget.Button;
import Android.widget.TextView;

public class Test extends Activity {

    private Handler mHandler = new Handler(); 
    private int labelNo    = 0;
    private long currTime  = 0L;
    private long mStartTime = 0L;
    TextView mTimeTextField;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mTimeTextField = (TextView)findViewById(R.id.timeTextFieldl);

        Button startButton = (Button)findViewById(R.id.start_button);
        startButton.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                   if (mStartTime == 0L) {
                        mStartTime = System.currentTimeMillis();
                        mHandler.removeCallbacks(mUpdateTimeTask);
                        mHandler.postDelayed(mUpdateTimeTask, 100);
                   }
            }
        });
    }

    private Runnable mUpdateTimeTask = new Runnable() {
           public void run() {
               final long start = mStartTime;
               //long millis = SystemClock.uptimeMillis() - start;
               long millis = SystemClock.uptimeMillis();
               int seconds = (int) (millis / 1000);
               int minutes = seconds / 60;
               seconds     = seconds % 60;

               //setContentView(mTimeTextField);  This will blow up if I use it

               if (seconds < 10) {
                   mTimeTextField.setText("" + minutes + ":0" + seconds);
               } else {
                   mTimeTextField.setText("" + minutes + ":" + seconds);            
               }

               //mHandler.postAtTime(this,
                   //    start + (((minutes * 60) + seconds + 1) * 1000));

               mHandler.postAtTime(this, 1000);
           }
        };

}

Par quelques suggestions, j'ai essayé d'ajouter: 

setContentView(mTimeLabel);

Mais cela va planter se plaindre de la vue de ne pas avoir un parent. Pour votre information, j'ai un:

setContentView(R.layout.main);

appeler ma onCreate().

22
bdelliott

Remplacer 

mHandler.postAtTime(this, 1000);

avec

mHandler.postDelayed(this, 1000);
19
Fedor
  1. Vous devez effectuer les mises à jour de l'interface utilisateur dans le fil de l'interface utilisateur.
  2. Vous devez créer un gestionnaire dans le thread d'interface utilisateur pour exécuter tâches dans le fil de l'interface utilisateur.

    public class MainActivity extends AppCompatActivity
        private Handler mHandler;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            mHandler = new Handler(); // This to create the Handler in the UI thread
            // ...
        }
    
5
david m lee

Cela pourrait être plus dans le sens de ce que vous recherchez:

private Runnable mUpdateTimeTask = new Runnable() {
       public void run() {

           final long start = mStartTime;
           long elapseTime = System.currentTimeMillis() - start;
           int seconds = (int) (elapseTime / 1000);
           int minutes = seconds / 60;
           seconds     = seconds % 60;

           if (seconds < 10) {
               mTimeTextField.setText("" + minutes + ":0" + seconds);
           } else {
               mTimeTextField.setText("" + minutes + ":" + seconds);            
           }

           // add a delay to adjust for computation time
           long delay = (1000 - (elapseTime%1000));

           mHandler.postDelayed(this, delay);
       }
    };

J'ai trouvé que c'était un bon moyen d'ajouter un temps à la vidéo

4
Laith Alnagem

la vue ne peut être affichée que sur le fil de l'interface utilisateur. vous devez démarrer le runnable en utilisant ru

1
Hariharan Veerappan

Assurez-vous que R.id.timeTextFieldl est un identifiant correct.

0
Fedor
if (seconds < 10) {
    mTimeTextField.setText("" + minutes + ":0" + seconds);
} else {
    mTimeTextField.setText("" + minutes + ":" + seconds);            
}

plus court est:

mTimeTextField.setText(minutes + ":" + (seconds < 10 ? "0" : "") + seconds);

mais le meilleur moyen est d'utiliser String.format ^

mTimeTextField.setText(String.format("%d:%s%d", minutes, (seconds < 10 ? "0" : ""), seconds);
0
Sergey