Wie rufe ich eine Funktion nach einer Verzögerung in Kotlin auf?


153

Gibt es als Titel eine Möglichkeit, eine Funktion nach einer Verzögerung (z. B. 1 Sekunde) in aufzurufen Kotlin ?

Antworten:


134

Sie können Schedule verwenden

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

Beispiel (danke @Nguyen Minh Binh - fand es hier: 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
Vielen Dank! Super einfach. Hier ein Beispiel gefunden jamie.mccrindle.org/2013/02/… Timer("SettingUp", false).schedule(500) { doSomething() }
Nguyen Minh Binh

9
Es wird kompiliert, wenn Sie diese beiden Importe hinzufügen: import java.util.Timer und import kotlin.concurrent.schedule
Customizer

3
@Matias Elorriaga, für mich, dies in eine neue Markendatei zu setzen, wird nicht kompiliert, sogar die Importe hinzufügen Customizer sagte
Sulfkain

3
Sie müssen es nicht in eine Datei einfügen, diese Methode ist Teil von stdlib, folgen Sie dem Link in der ersten Zeile der Antwort,
Matias Elorriaga

3
Ich dachte ursprünglich, dass dies auch nach dem Import nicht kompiliert werden würde kotlin.concurrent.schedule, da Kotlin sich lediglich über eine Signaturfehlanpassung beschwerte, aber dann wurde mir klar, dass ich versuchte, ein Int anstelle eines Long zu übergeben. Es wurde kompiliert, nachdem das korrigiert wurde.
Joe Lapp

178

Es gibt auch eine Option zu verwenden Handler -> postDelayed

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

18
Bitte fügen Sie hinzu, dass es nur auf Android verfügbar ist, da die Frage nach einer allgemeinen Kotlin-Methode fragt (obwohl es das Android-Tag hat)
Yoav Sternberg

5
Es ist nicht konstruktiv von Ihrer Seite. Infolgedessen, wenn Benutzer Android-Tag suchen, könnte denken, dass dies eine falsche Antwort ist.
Bogdan Ustyak

9
Für Android ist es besser, Handler als Timer zu verwenden: stackoverflow.com/questions/20330355/timertask-or-handler
woprandi

Ich denke, Sie sollten einen Code zum Entfernen von Handlern nach Beendigung der Aktivität / des Fragments hinzufügen.
CoolMind

Dies wird nicht auf dem UI-Thread ausgeführt, wenn Sie dies beabsichtigt haben.
AndroidDev

93

Viele Möglichkeiten

1. HandlerKlasse verwenden

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

2. TimerKlasse verwenden

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

Kürzer

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

Kürzeste

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

3. ExecutorsKlasse verwenden

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

1
und was ist Ihrer Meinung nach die beste Lösung hier?
Tamim Attafi

1
Wahrscheinlich der erste, der einen Handler verwendet. Siehe stackoverflow.com/a/40339630/1159930
Markymark

36

Sie müssen die folgenden zwei Bibliotheken importieren:

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

und danach verwenden Sie es auf diese Weise:

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

27

Sie könnten launcheine Coroutine, delayes und dann die Funktion aufrufen:

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

Wenn Sie sich außerhalb einer Klasse oder eines Objekts befinden GlobalScope, müssen Sie die Coroutine dort ausführen, andernfalls wird empfohlen, die CoroutineScopein der umgebenden Klasse zu implementieren , um bei Bedarf alle diesem Bereich zugeordneten Coroutinen abzubrechen.


Vielen Dank! Seltsam, dass Coroutinen erst 2018 erwähnt wurden.
CoolMind

@coolMind sie sind seit ein paar Monaten stabil, also sind sie ziemlich neu ...
Jonas Wilms

Ja, von Oktober bis November, aber existierte vorher.
CoolMind

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

1
Können Sie mir bitte erklären, warum ich "timerTask" anstatt nur Klammern schreiben muss?
Hugo Passos

2
Ich denke du tust es. Timer.schedule()erwartet ein TimerTaskals erstes Argument. kotlin.concurrent.timerTask()Wraps das gegebene Lambda in eine TimerTaskInstanz. Siehe hier: kotlinlang.org/api/latest/jvm/stdlib/kotlin.concurrent/…
Blieque

Das angegebene Beispiel kann auch zu einer Zeile zusammengefasst werden, wenn das TimerObjekt nicht mehr als einmal verwendet wird, z Timer().schedule(timerTask { ... }, 3000). Eine Kotlin-freundlichere Option ist ebenfalls verfügbar. siehe jonguers antwort.
Blieque

10

Ein einfaches Beispiel, um einen Toast nach 3 Sekunden zu zeigen :

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

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

1
Kann ich den Anruf abbrechen?
Eduardo Oliveros

6

Wenn Sie nach einer generischen Verwendung suchen, ist hier mein Vorschlag:

Erstellen Sie eine Klasse mit dem Namen Run:

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

Und verwenden Sie wie folgt:

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

Sie können dies als Erweiterungsfunktion vereinfachen
Vlad

@ Ogcan, mehr kotlinische Lamda Run.after(1000) { toRun() }. Bin ich richtig
binrebin

0

Ich habe die Verwendung von SingleThread empfohlen, da Sie es nach der Verwendung nicht beenden müssen. Außerdem ist die Methode " stop ()" in der Kotlin-Sprache veraltet.

private fun mDoThisJob(){

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

    }, 1, 1, TimeUnit.SECONDS)
}

Darüber hinaus können Sie es für regelmäßige Arbeiten verwenden. Es ist sehr nützlich. Wenn Sie für jede Sekunde einen Job ausführen möchten, können Sie folgende Parameter festlegen:

Executors.newSingleThreadScheduledExecutor (). ScheduleAtFixedRate (Ausführbarer Befehl, lange Anfangsverzögerung, langer Zeitraum, TimeUnit-Einheit);

TimeUnit-Werte sind: NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTEN, STUNDEN, TAGE.

@canerkaseler

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.