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?

Nguyen Minh Binh
la source

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()
}
Matias Elorriaga
la source
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)
Bogdan Ustyak
la source
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)
Khemraj
la source
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
}
jonguer
la source
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.

Jonas Wilms
la source
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)
varghesekutty
la source
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()
}
Zeero0
la source
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.
})
Ogulcan Orhan
la source
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

canerkaseler
la source