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 spécifié. Dans l'objectif c il y avait quelque chose comme:

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

Est-il un équivalent de cette méthode dans android avec java? Par exemple, je dois pouvoir appeler une méthode après 5 secondes.

public void DoSomething()
{
     //do something here
}
596
demandé sur Gautam 2010-06-18 22:24:19

22 réponses

meilleure version:

final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
  @Override
  public void run() {
    //Do something after 100ms
  }
}, 100);
1517
répondu kontinuity 2012-02-06 19:55:23

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

new Timer().schedule(new TimerTask() {          
    @Override
    public void run() {
        // this code will be executed after 2 seconds       
    }
}, 2000);
263
répondu Jules Colle 2012-06-23 01:16:35

Note: cette réponse a été donnée lorsque la question ne spécifiait pas Android comme le contexte. Pour une réponse spécifique à L'interface utilisateur Android regardez ici.


il semble que L'API Mac OS laisse le thread courant continuer, et planifie la tâche de fonctionner asynchrone. En Java, la fonction équivalente est fournie par le paquet java.util.concurrent . Je ne suis pas sûr de ce que les limites 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);
  ⋮
}
177
répondu erickson 2017-05-23 11:47:26

pour exécuter quelque chose dans le Thread après 5 secondes:

new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
    @Override
    public void run() {
        //Do something here
    }
}, 5000);
89
répondu pomber 2016-02-04 16:29:13

vous pouvez utiliser Handler inside UIThread:

runOnUiThread(new Runnable() {

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

    }
});
36
répondu Hossam Ghareeb 2016-02-04 16:28:46

Merci pour toutes les bonnes réponses, j'ai trouvé une solution qui convient 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
    }
}
34
répondu aryaxt 2016-02-04 16:33:25

si vous devez utiliser le Gestionnaire, mais que vous êtes dans un autre thread, vous pouvez utiliser runonuithread pour exécuter le gestionnaire dans le thread UI. Cela vous sauvera des Exceptions lancées en demandant d'appeler Looper.Prepare()

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                //Do something after 1 second
            }
        }, 1000);
    }
});

a l'air assez désordonné, mais c'est l'un des chemins.

20
répondu noob 2015-02-09 18:47:22

voir cette démo:

import java.util.Timer;
import java.util.TimerTask;

class Test {
     public static void main( String [] args ) {
          int delay = 5000;// in ms 

          Timer timer = new Timer();

          timer.schedule( new TimerTask(){
             public void run() { 
                 System.out.println("Wait, what..:");
              }
           }, delay);

           System.out.println("Would it run?");
     }
}
19
répondu OscarRyz 2010-06-18 18:45:34

je préfère utiliser la méthode View.postDelayed() , code simple ci-dessous:

mView.postDelayed(new Runnable() {
    @Override
    public void run() {
        // Do something after 1000 ms
    }
}, 1000);
15
répondu codezjx 2018-01-23 13:31:47

voici ma solution la plus courte:

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        //Do something after 100ms
    }
}, 100);
12
répondu Alecs 2017-01-29 14:47:20
final Handler handler = new Handler(); 
Timer t = new Timer(); 
t.schedule(new TimerTask() { 
    public void run() { 
        handler.post(new Runnable() { 
            public void run() { 
                //DO SOME ACTIONS HERE , THIS ACTIONS WILL WILL EXECUTE AFTER 5 SECONDS...
            }
        }); 
    } 
}, 5000); 
9
répondu Vishnu 2016-02-04 16:31:06

je suggère le Timer , il vous permet de programmer une méthode pour être appelé sur un intervalle très spécifique. Cela ne bloquera pas votre UI, et gardera votre application en résonance pendant que la méthode est exécutée.

l'autre option, est la méthode wait (); , qui bloque le thread courant pendant la durée spécifiée. Cela fera que votre UI cessera de répondre si vous faites cela sur le thread de L'UI.

5
répondu Nate 2010-06-18 18:39:00

si vous utilisez Android Studio 3.0 et plus, vous pouvez utiliser des expressions lambda. La méthode callMyMethod() s'appelle après 2 secondes:

new Handler().postDelayed(() -> callMyMethod(), 2000);

dans le cas où vous devez annuler tous les runnables retardés:

Handler handler = new Handler();
handler.postDelayed(() -> callMyMethod(), 2000);

// When you need to cancel all your posted runnables just use:
handler.removeCallbacksAndMessages(null);
5
répondu vovahost 2017-11-12 14:53:46

vous pouvez l'utiliser pour la Solution la plus simple:

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        //Write your code here
    }
}, 5000); //Timer is in ms here.

autrement, ci-dessous peut être une autre solution utile propre:

new Handler().postDelayed(() -> 
{/*Do something here*/}, 
5000); //time in ms
5
répondu Crime_Master_GoGo 2018-01-29 05:08:55

j'ai créé une méthode plus simple pour appeler cela.

public static void CallWithDelay(long miliseconds, final Activity activity, final String methodName)
    {
        new Handler().postDelayed(new Runnable() {

            @Override
            public void run() {
                try {
                    Method method =  activity.getClass().getMethod(methodName);
                    method.invoke(activity);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }, miliseconds);
    }

Pour l'utiliser, il suffit d'appeler : .CallWithDelay(5000, this, "DoSomething");

3
répondu HelmiB 2016-03-16 07:28:43

vous pouvez le rendre beaucoup plus propre en utilisant les expressions lambda nouvellement introduites:

new Handler().postDelayed(() -> {/*your code here*/}, time);
3
répondu Alnour Alharin 2018-09-18 04:18:26

il est très facile d'utiliser le CountDownTimer . Pour plus de détails https://developer.android.com/reference/android/os/CountDownTimer.html

import android.os.CountDownTimer;

// calls onTick every second, finishes after 3 seconds
new CountDownTimer(3000, 1000) { 

   public void onTick(long millisUntilFinished) {
      Log.d("log", millisUntilFinished / 1000);
   }

   public void onFinish() {
      // called after count down is finished
   } 
}.start();
2
répondu Abdul Rizwan 2017-09-11 13:26:34

tout le monde semble oublier de nettoyer le Handler avant d'y poster une nouvelle runnable ou un message. Autrement, ils pourraient s'accumuler et causer de mauvais comportements.

handler.removeMessages(int what);
// Remove any pending posts of messages with code 'what' that are in the message queue.

handler.removeCallbacks(Runnable r)
// Remove any pending posts of Runnable r that are in the message queue.
1
répondu Dan Alboteanu 2017-10-26 18:03:33

voici un autre moyen délicat: il ne lancera pas d'exception lorsque les éléments exécutables de l'UI change.

public class SimpleDelayAnimation extends Animation implements Animation.AnimationListener {

    Runnable callBack;

    public SimpleDelayAnimation(Runnable runnable, int delayTimeMilli) {
        setDuration(delayTimeMilli);
        callBack = runnable;
        setAnimationListener(this);
    }

    @Override
    public void onAnimationStart(Animation animation) {

    }

    @Override
    public void onAnimationEnd(Animation animation) {
        callBack.run();
    }

    @Override
    public void onAnimationRepeat(Animation animation) {

    }
}

Vous pouvez appeler l'animation comme ceci:

view.startAnimation(new SimpleDelayAnimation(delayRunnable, 500));
L'Animation

peut être attachée à n'importe quelle vue.

1
répondu cdytoby 2018-09-18 04:18:05

donc il y a quelques choses à considérer ici car il y a tellement de façons d'écorcher ce chat. Bien que les réponses aient déjà toutes été données sélectionnées et choisies. Je pense qu'il est important que cette question soit réexaminée à l'aide de lignes directrices appropriées sur le codage afin d'éviter que quiconque aille dans la mauvaise direction simplement à cause de la "réponse simple choisie par la majorité".

alors tout d'abord, nous allons discuter de la réponse simple post retardé qui est le gagnant choisi réponse globale dans ce fil.

deux ou trois choses à considérer. Après le délai de post, vous pouvez rencontrer des fuites de mémoire, des objets morts, des cycles de vie qui ont disparu, et plus encore. Donc de gérer correctement est important. Vous pouvez le faire dans un couple des manières.

pour le développement moderne, je fournirai à KOTLIN

voici un exemple simple d'utilisation du thread de L'UI sur un rappel et de confirmer que votre activité est toujours vivante et en bonne santé lorsque vous frappez votre rappel.

  Handler(Looper.getMainLooper()).postDelayed({
            if(activity != null && activity?.isFinishing == false){
                txtNewInfo.visibility = View.GONE
            }
        }, NEW_INFO_SHOW_TIMEOUT_MS)

cependant, ce n'est toujours pas parfait car il n'y a aucune raison de répondre à votre appel si l'activité a disparu. donc une meilleure façon serait de garder une référence à elle et supprimer ses rappels comme ceci.

    private fun showFacebookStylePlus1NewsFeedOnPushReceived(){
        A35Log.v(TAG, "showFacebookStylePlus1NewsFeedOnPushReceived")
        if(activity != null && activity?.isFinishing == false){
            txtNewInfo.visibility = View.VISIBLE
            mHandler.postDelayed({
                if(activity != null && activity?.isFinishing == false){
                    txtNewInfo.visibility = View.GONE
                }
            }, NEW_INFO_SHOW_TIMEOUT_MS)
        }
    }

et bien sûr gérer le nettoyage sur l'onPause afin qu'il ne frappe pas le rappel.

    override fun onPause() {
        super.onPause()
        mHandler.removeCallbacks(null)
    }

maintenant que nous avons parlé à travers l'évidence, parlons d'une option plus propre avec les temps modernes coroutines et kotlin:). Si vous ne les utilisez pas encore,vous ratez vraiment.

   fun doActionAfterDelay() 
        launch(UI) {
            delay(MS_TO_DELAY)           
            actionToTake()
        }
    }

ou si vous voulez toujours faire un lancement D'UI sur cette méthode, vous pouvez simplement faire:

  fun doActionAfterDelay() = launch(UI){ 
      delay(MS_TO_DELAY)           
      actionToTake()
  }

bien sûr, tout comme le PostDelayed vous devez vous assurer de gérer l'annulation de sorte que vous pouvez soit faire les contrôles d'activité après l'appel de retard ou vous pouvez l'Annuler dans la onPause tout comme l'autre route.

var mDelayedJob: Job? = null
fun doActionAfterDelay() 
   mDelayedJob = launch(UI) {
            try {
               delay(MS_TO_DELAY)           
               actionToTake()
            }catch(ex: JobCancellationException){
                showFancyToast("Delayed Job canceled", true, FancyToast.ERROR, "Delayed Job canceled: ${ex.message}")
            }
        }
   }
}

//poignée nettoyage

override fun onPause() {
   super.onPause()
   if(mDelayedJob != null && mDelayedJob!!.isActive) {
      A35Log.v(mClassTag, "canceling delayed job")
      mDelayedJob?.cancel() //this should throw CancelationException in coroutine, you can catch and handle appropriately
   }
}

si vous mettez le lancement(UI) dans la signature de la méthode la tâche peut être assignée dans la ligne d'appel du code.

donc la morale de l'histoire est d'être en sécurité avec vos actions retardées, assurez-vous de supprimer vos rappels, ou d'annuler vos emplois et bien sûr de confirmer que vous avez le cycle de vie droit de toucher des éléments sur votre retard de rappel complet. Les Coroutines offrent également des actions annulables.

vaut également la peine de noter que vous devez généralement gérer les diverses exceptions qui peuvent venir avec des coroutines. Par exemple, une annulation, une exception, un délai, Tout ce que vous décidez d'utiliser. Voici un exemple plus avancé si vous décidez de vraiment commencer à utiliser coroutines.

   mLoadJob = launch(UI){
            try {
                //Applies timeout
                withTimeout(4000) {
                    //Moves to background thread
                    withContext(DefaultDispatcher) {
                        mDeviceModelList.addArrayList(SSDBHelper.getAllDevices())
                    }
                }

                //Continues after async with context above
                showFancyToast("Loading complete", true, FancyToast.SUCCESS)
            }catch(ex: JobCancellationException){
                showFancyToast("Save canceled", true, FancyToast.ERROR, "Save canceled: ${ex.message}")
            }catch (ex: TimeoutCancellationException) {
                showFancyToast("Timed out saving, please try again or press back", true, FancyToast.ERROR, "Timed out saving to database: ${ex.message}")
            }catch(ex: Exception){
                showFancyToast("Error saving to database, please try again or press back", true, FancyToast.ERROR, "Error saving to database: ${ex.message}")
            }
        }
1
répondu Sam 2018-09-25 15:56:23

une solution appropriée pour android:

private static long SLEEP_TIME = 2 // for 2 second
.
.
MyLauncher launcher = new MyLauncher();
            launcher.start();
.
.
private class MyLauncher extends Thread {
        @Override
        /**
         * Sleep for 2 seconds as you can also change SLEEP_TIME 2 to any. 
         */
        public void run() {
            try {
                // Sleeping
                Thread.sleep(SLEEP_TIME * 1000);
            } catch (Exception e) {
                Log.e(TAG, e.getMessage());
            }
            //do something you want to do
           //And your code will be executed after 2 second
        }
    }
0
répondu Faakhir 2014-09-28 07:21:32

Voici la réponse à Kotlin vous paresseux, les gens paresseux:

Handler().postDelayed({
//doSomethingHere()
}, 1000)
0
répondu Daniel Wilson 2018-09-25 15:10:35