Android : Répéter une action (timer)

Dans android pour répéter une action à intervalles réguliers on peut utiliser timertask , mais pour d’obscures raisons , il m’est arrivé d’avoir des problèmes avec ce timer.
Du coup, une solution qui semble fonctionner à merveille est l’utilisation d’un handler et d’un runnable :

private Handler myHandler;
private Runnable myRunnable = new Runnable() {
@Override
public void run() {
    // Code à éxécuter de façon périodique

    myHandler.postDelayed(this,500);
    }
};

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.myLayout);

    myHandler = new Handler();
    myHandler.postDelayed(myRunnable,500); // on redemande toute les 500ms
}

public void onPause() {
    super.onPause();
    if(myHandler != null)
        myHandler.removeCallbacks(myRunnable); // On arrete le callback
}

On demande simplement au handler un appel retardé du runnable (ici 500ms) puis dans le runnable on répète cette opération.
On rentre ainsi dans une « boucle infinie » qui nous permet d’exécuter le code du runnable à intervale régulier.

Ne pas oublier de stopper le tout avant de quitter l’activité (ou avant) via removeCallback(Runnable).

14 réflexions sur « Android : Répéter une action (timer) »

  1. Gilles

    Il manque un ‘s’ à « removeCallbacks » et un ‘;’ à la fin de « private Runnable myRunnable = new Runnable(){………}; »

    Si non, merci du bout de code, ça va me servir pour m’amuser un peu, je pousserai le sujet plus loin quand j’aurai le temps ! 🙂

    Répondre
  2. Jean Marchadier

    Bonjour,
    J’ai fais un petit essai avec API 22. Compilation ok, j’obtiens mon apk. Mais l’application plante à l’exécution.
    Je suis débutant. Pouvez-vous m’aider un peu pour savoir ce qui ne colle pas?
    Voici le code:

    public class MainActivity extends Activity {
    private Handler myHandler;
    private Runnable myRunnable = new Runnable() {
    public void run() {
    // Code à éxécuter de façon périodique
    TextView t = (TextView) findViewById(R.string.hello_world);
    t.setText("1234");
    myHandler.postDelayed(this,500);
    }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    myHandler = new Handler();
    myHandler.postDelayed(myRunnable,500);
    }

    public void onPause() {
    super.onPause();
    if(myHandler != null)
    myHandler.removeCallbacks(myRunnable); // On arrete le callback
    }
    }

    Répondre
    1. Olivier Auteur de l’article

      findViewById(R.string.hello_world);
      ne peux pas fonctionner , un widget se selectionne par son id , pas par sa valeur. Par exemple :
      findViewById(R.id.id_du_textview);

      Répondre
      1. Jean Marchadier

        J’ai mis

        TextView t = (TextView) findViewById(R.id.textView2);

        à la place de

        TextView t = (TextView) findViewById(R.string.hello_world);

        Mon Layout:


        Le programe se charge dans l’émulateur puis se plante à l’exécution.
        Si je mets t.setText(« 1234 »); en commentaire, ça tourne avec la valeur du string définie au départ.
        J’ai essayé dans mon smartphone, pareil..

        Répondre
        1. Olivier Auteur de l’article

          Regarde l’erreur fournit par le logcat.
          Ton premier code simplement modifié avec ma remarque (et le layout modifié en conséquence) fonctionne

          Répondre
          1. Jean Marchadier

            En fait ça fonctionne. Le problème provient de la dernière version d’eclipse. avec le sdk.
            On est obligé d’accepter le projet par défaut qui comporte « appcompat_v7 » sinon ça ne marche pas au runtime. J’gnore pourquoi.
            Ca génère un fichier apk de 1Mo au lieu de 500Ko.
            Merci de ton aide..

  3. Olivier Auteur de l’article

    Appcompat est indispensable puisqu’elle permet de rendre compatible une grosse partie des dernières API sur des anciens modèles avec un android pas à jour

    Répondre
    1. Jean Marchadier

      Merci. J’ai perdu des heures avec ça. Je vais pouvoir enfin faire mon projet.
      En tous cas, tu m’à l’air d’en connaître un rayon. Bravo et bonne continuation.
      Jean.

      Répondre
  4. ouedraogo mahomed

    Bonjour!!! merci pour se tutoriel qui a premiere vue entouka semble etre le sauveur!!!
    jai suivi votre tutoriel mais je ne m’en sort pas!!!!
    android studio souligne certainne fonction et du coup je ne m’en sort pas!!!! svp help me!!!!!!!

    dabord quand je met cette ligne  » myHandler.postDelayed(this,500);  » dans le declaration du « myRunnable », android studion colorie le « postDelayed » en rougeet dit: (Cannot resolve method ‘postDelayed(java.lang.runnable, int)’ ).

    ensuite quand je met les deux lignes :
    myHandler = new Handler();
    myHandler.postDelayed(myRunnable,500);
    dans le onCreate(), le « new Handler() » se souligne en rouge et dit le message derreur:( Handler is abstract; cannot be instancied)
    et la deuxieme ligne  » myHandler.postDelayed()  » m’affiche le meme message que jai decrit en haut!!!

    SIL VOUS PLAIT, aider moi, jai foi que cest se tuto qui va me sortir de l »impasse!!!!!!! aider moi a decanter ces erreurs please!!!!!!!!

    Répondre
  5. jose

    Bonjour, merci pour cette fonctionnalité car j’en ai bien besoin; mon seul problème c’est que j’aimerai le lancer lorsqu’on clique sur un bouton parce là quand je lance l’app ça marche tout de suite, pouvez-vous m’aider sur celà

    Répondre
    1. Olivier Auteur de l’article

      Il suffit d’appeler myHandler.postDelayed(myRunnable,500); dans le listener de votre bouton plutôt que dans le onCreate() comme dans l’exemple

      Répondre

Répondre à Gilles Annuler la réponse

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *