Comment appeler une fonction après un délai dans Kotlin?


154

En tant que titre, existe-t-il un moyen d'appeler une fonction après un délai (1 seconde par exemple) dans Kotlin?

Réponses:


133

Vous pouvez utiliser Schedule

inline fun Timer.schedule(
    delay: Long, 
    crossinline action: TimerTask.() -> Unit
): TimerTask (source)

exemple (merci @Nguyen Minh Binh - trouvé ici: http://jamie.mccrindle.org/2013/02/exploring-kotlin-standard-library-part-3.html )

import java.util.Timer
import kotlin.concurrent.schedule

Timer("SettingUp", false).schedule(500) { 
   doSomething()
}

16
Merci! Super facile. J'ai trouvé un exemple ici jamie.mccrindle.org/2013/02/…Timer("SettingUp", false).schedule(500) { doSomething() }
Nguyen Minh Binh

9
Il compile, si vous ajoutez ces deux importations: import java.util.Timer et import kotlin.concurrent.schedule
Customizer

3
@Matias Elorriaga, pour moi, mettre ceci sur un nouveau fichier de marque ne compile pas, même en ajoutant les importations Customizer a dit
Sulfkain

3
vous n'avez pas besoin de le mettre dans un fichier, cette méthode fait partie de stdlib, suivez le lien dans la première ligne de la réponse,
Matias Elorriaga

3
Au départ, je pensais que cela ne se compilerait pas même après l'importation kotlin.concurrent.schedule, car Kotlin se plaignait simplement d'une incompatibilité de signature, mais j'ai ensuite réalisé que j'essayais de passer un Int au lieu d'un Long. Il a été compilé après avoir corrigé cela.
Joe Lapp

178

Il existe également une option à utiliser Handler -> postDelayed

 Handler().postDelayed({
                    //doSomethingHere()
                }, 1000)

18
Veuillez ajouter qu'il n'est disponible que sur Android, car la question demande une méthode kotlin générale (bien qu'elle ait la balise Android)
Yoav Sternberg

5
Ce n'est pas constructif de votre part. En conséquence, lorsque les utilisateurs rechercheront une balise Android, il se peut que ce soit une mauvaise réponse.
Bogdan Ustyak

9
Pour Android, il vaut mieux utiliser Handler que Timer: stackoverflow.com/questions/20330355/timertask-or-handler
woprandi

Je pense que vous devriez ajouter un code pour supprimer les gestionnaires après la fin de l'activité / du fragment.
CoolMind

Cela ne fonctionnera pas sur le thread de l'interface utilisateur si vous aviez l'intention de le faire.
AndroidDev

93

Plusieurs façons

1. Utilisation de la Handlerclasse

Handler().postDelayed({
    TODO("Do something")
    }, 2000)

2. Utilisation de la Timerclasse

Timer().schedule(object : TimerTask() {
    override fun run() {
        TODO("Do something")
    }
}, 2000)

Plus court

Timer().schedule(timerTask {
    TODO("Do something")
}, 2000)

Le plus court

Timer().schedule(2000) {
    TODO("Do something")
}

3. Utilisation de la Executorsclasse

Executors.newSingleThreadScheduledExecutor().schedule({
    TODO("Do something")
}, 2, TimeUnit.SECONDS)

1
et quelle est selon vous la meilleure solution ici?
Tamim Attafi

1
Probablement le premier utilisant un Handler. Voir stackoverflow.com/a/40339630/1159930
Markymark

36

Vous devez importer les deux bibliothèques suivantes:

import java.util.*
import kotlin.concurrent.schedule

et après cela, utilisez-le de cette manière:

Timer().schedule(10000){
    //do something
}

27

Vous pouvez launchune coroutine, delaypuis appeler la fonction:

 /*GlobalScope.*/launch {
   delay(1000)
   yourFn()
 }

Si vous êtes en dehors d'une classe ou d'un objet prefend GlobalScopepour laisser la coroutine s'exécuter là-bas, sinon il est recommandé d'implémenter le CoroutineScopedans la classe environnante, ce qui permet d'annuler toutes les coroutines associées à cette portée si nécessaire.


Merci! Étrange, que les coroutines n'aient été mentionnées qu'en 2018.
CoolMind

@coolMind ils sont stables depuis quelques mois, donc ils sont assez nouveaux ...
Jonas Wilms

Oui, d'octobre à novembre, mais existait avant.
CoolMind

23
val timer = Timer()
timer.schedule(timerTask { nextScreen() }, 3000)

1
Pouvez-vous s'il vous plaît m'expliquer pourquoi j'ai besoin d'écrire "timerTask" au lieu de simples accolades?
Hugo Passos

2
Je pense que oui. Timer.schedule()attend un TimerTaskcomme premier argument. kotlin.concurrent.timerTask()enveloppe le lambda donné dans une TimerTaskinstance. Voir ici: kotlinlang.org/api/latest/jvm/stdlib/kotlin.concurrent / ...
Blieque

De plus, l'exemple donné peut être condensé sur une ligne si l' Timerobjet ne sera pas utilisé plus d'une fois, par exemple Timer().schedule(timerTask { ... }, 3000). Une option plus conviviale pour Kotlin est également disponible; voir la réponse de Jonguer.
Blieque

10

Un exemple simple pour montrer un toast après 3 secondes :

fun onBtnClick() {
    val handler = Handler()
    handler.postDelayed({ showToast() }, 3000)
}

fun showToast(){
    Toast.makeText(context, "Its toast!", Toast.LENGTH_SHORT).show()
}

1
puis-je annuler l'appel?
Eduardo Oliveros

6

Si vous recherchez un usage générique, voici ma suggestion:

Créez une classe nommée comme Run :

class Run {
    companion object {
        fun after(delay: Long, process: () -> Unit) {
            Handler().postDelayed({
                process()
            }, delay)
        }
    }
}

Et utilisez comme ceci:

Run.after(1000, {
    // print something useful etc.
})

Vous pouvez simplifier cela en tant que fonction d'extension
Vlad

@Ogulcan, plus lamda kotlinique Run.after(1000) { toRun() }. Ai-je raison
binrebin

0

J'ai recommandé d'utiliser SingleThread car vous n'avez pas à le tuer après utilisation. De plus, la méthode " stop ()" est obsolète en langage Kotlin.

private fun mDoThisJob(){

    Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate({
        //TODO: You can write your periodical job here..!

    }, 1, 1, TimeUnit.SECONDS)
}

De plus, vous pouvez l'utiliser pour un travail périodique. C'est très utile. Si vous souhaitez faire un travail pour chaque seconde, vous pouvez en définir les paramètres:

Executors.newSingleThreadScheduledExecutor (). ScheduleAtFixedRate (commande Runnable, long initialDelay, longue période, unité TimeUnit);

Les valeurs de TimeUnit sont: NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS.

@canerkaseler

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.