920 votes

Comment appeler une méthode après un délai dans Android

Je veux pouvoir appeler la méthode suivante après un délai déterminé. Dans l'objectif c il y avait quelque chose comme :

[self performSelector:@selector(DoSomething) withObject:nil afterDelay:5];

Existe-t-il un équivalent de cette méthode dans Android avec java ? Par exemple, j'ai besoin de pouvoir appeler une méthode après 5 secondes.

public void DoSomething()
{
     //do something here
}

2200voto

kontinuity Points 4025

Kotlin

Handler(Looper.getMainLooper()).postDelayed({
    //Do something after 100ms
}, 100)

Java

final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        //Do something after 100ms
    }
}, 100);

0 votes

Cela a parfaitement fonctionné et s'est intégré à la méthode à partir de laquelle je devais faire l'appel. Merci.

0 votes

Même chose ici ; je l'utilise pour retarder le passage des fragments afin d'améliorer l'animation.

1 votes

C'est peut-être la pièce finale qui a aidé à cimenter les concepts de handler/threading d'Android dans ma tête. Excellent :)

373voto

Jules Colle Points 2482

Je ne pouvais utiliser aucune des autres réponses dans mon cas. J'ai utilisé le Timer natif de Java à la place.

new Timer().schedule(new TimerTask() {          
    @Override
    public void run() {
        // this code will be executed after 2 seconds       
    }
}, 2000);

48 votes

Cette solution est meilleure que celles qui utilisent le Handler, car elle ne présente pas de problèmes de Looper lorsque le Handler n'est pas exécuté sur le thread de l'interface utilisateur.

33 votes

Vous devez garder une référence à votre timer afin de l'annuler lorsqu'il n'est plus nécessaire selon la doc Android : "Lorsqu'un timer n'est plus nécessaire, les utilisateurs doivent appeler cancel(), qui libère le thread du timer et les autres ressources. Les timers qui ne sont pas explicitement annulés peuvent conserver les ressources indéfiniment."

18 votes

Attention ! Ceci ne fonctionne pas sur le thread de l'interface utilisateur. L'exécution sur le thread de l'interface utilisateur a provoqué une erreur fatale : Android.view.ViewRootImpl$CalledFromWrongThreadException : Seul le thread original qui a créé une hiérarchie de vues peut toucher ses vues.

189voto

erickson Points 127945

Note : Cette réponse a été donnée lorsque la question ne spécifiait pas Android comme contexte. Pour une réponse spécifique au thread Android UI regardez ici.


Il semble que l'API Mac OS laisse le fil d'exécution en cours se poursuivre et planifie l'exécution de la tâche de manière asynchrone. En Java, la fonction équivalente est fournie par la fonction java.util.concurrent paquet. Je ne suis pas sûr des limitations qu'Android pourrait imposer.

private static final ScheduledExecutorService worker = 
  Executors.newSingleThreadScheduledExecutor();

void someMethod() {
  ⋮
  Runnable task = new Runnable() {
    public void run() {
      /* Do something… */
    }
  };
  worker.schedule(task, 5, TimeUnit.SECONDS);
  ⋮
}

3 votes

Cela n'appelle jamais le Runnable pour moi

14 votes

Remarque : cela vous permet également de annuler la tâche plus tard, ce qui peut être utile dans certaines situations. Il suffit de stocker une référence à la ScheduledFuture<?> retourné par worker.schedule() et appeler son cancel(boolean) méthode.

0 votes

Je pense que cette réponse est dépassée. .schedule ne semble plus être une méthode de Runnable... ? :/

45voto

Hossam Ghareeb Points 1202

Vous pouvez utiliser le Handler dans UIThread :

runOnUiThread(new Runnable() {

    @Override
    public void run() {
        new Handler().postDelayed(new Runnable() {
           @Override
           public void run() {
               //add your code here
          }
        }, 1000);           
    }
});

40voto

aryaxt Points 15011

Merci pour toutes les bonnes réponses, j'ai trouvé une solution qui répond le mieux à mes besoins.

Handler myHandler = new DoSomething();
Message m = new Message();
m.obj = c;//passing a parameter here
myHandler.sendMessageDelayed(m, 1000);

class DoSomething extends Handler {
    @Override
    public void handleMessage(Message msg) {
      MyObject o = (MyObject) msg.obj;
      //do something here
    }
}

0 votes

Est-ce que je peux utiliser cette approche pour avoir un retour tactile sur le clic d'un élément... view.setColor(some_color) et ensuite supprimer cette couleur dans le Handler après x secondes... ?

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