Come chiamare una funzione dopo il ritardo in Kotlin?


154

Come titolo, c'è un modo per chiamare una funzione dopo il ritardo (ad esempio 1 secondo) in Kotlin?

Risposte:


134

È possibile utilizzare Pianifica

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

esempio (grazie @Nguyen Minh Binh - l'ho trovato qui: 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
Grazie! Super facile. Abbiamo trovato un esempio qui jamie.mccrindle.org/2013/02/… Timer("SettingUp", false).schedule(500) { doSomething() }
Nguyen Minh Binh

9
Viene compilato se si aggiungono queste due importazioni: import java.util.Timer e import kotlin.concurrent.schedule
Customizer

3
@Matias Elorriaga, per me, non è possibile compilare questo file su un nuovo file di marca, anche aggiungendo le importazioni personalizzate da Customizer
Sulfkain

3
non è necessario inserirlo in un file, tale metodo fa parte di stdlib, seguire il collegamento nella prima riga della risposta,
Matias Elorriaga,

3
Inizialmente pensavo che non sarebbe stato compilato nemmeno dopo l'importazione kotlin.concurrent.schedule, perché Kotlin si è semplicemente lamentato di una mancata corrispondenza della firma, ma poi mi sono reso conto che stavo cercando di passare un Int anziché un Long. Si è compilato dopo averlo corretto.
Joe Lapp,

178

C'è anche un'opzione da usare Handler -> postDelayed

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

18
Si prega di aggiungere che è disponibile solo su Android, poiché la domanda richiede un metodo kotlin generale (anche se ha il tag Android)
Yoav Sternberg

5
Non è costruttivo dalla tua parte. Di conseguenza, quando gli utenti cercheranno tag Android potrebbero pensare che questa sia una risposta sbagliata.
Bogdan Ustyak,

9
Per Android, è meglio usare Handler di Timer: stackoverflow.com/questions/20330355/timertask-or-handler
woprandi

Penso che dovresti aggiungere un codice per rimuovere i gestori al termine dell'attività / frammento.
CoolMind

Questo non verrà eseguito sul thread dell'interfaccia utente se si intendeva farlo.
AndroidDev

93

Molti modi

1. Uso della Handlerclasse

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

2. Uso della Timerclasse

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

Più breve

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

Più breve

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

3. Uso della Executorsclasse

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

1
e quale pensi sia la migliore soluzione qui?
Tamim Attafi,

1
Probabilmente il primo ad usare un gestore. Vedi stackoverflow.com/a/40339630/1159930
Markymark

36

Devi importare le seguenti due librerie:

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

e dopo usalo in questo modo:

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

27

È possibile launchun coroutine, delayquindi chiamare la funzione:

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

Se si è al di fuori di una classe o di un oggetto anteposto GlobalScopeper consentire l'esecuzione della coroutine, altrimenti si consiglia di implementare la CoroutineScopeclasse circostante, che consente di annullare tutte le coroutine associate a tale ambito, se necessario.


Grazie! Strano, che le coroutine sono state menzionate solo nel 2018.
CoolMind

@coolMind sono stabili da qualche mese, quindi sono abbastanza nuovi ...
Jonas Wilms

Sì, da ottobre a novembre, ma esisteva prima.
CoolMind

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

1
Potete per favore spiegarmi perché devo scrivere "timerTask" anziché solo parentesi graffe?
Hugo Passos,

2
Penso che tu lo faccia. Timer.schedule()si aspetta un TimerTaskcome primo argomento. kotlin.concurrent.timerTask()avvolge la lambda data in TimerTaskun'istanza. Vedi qui: kotlinlang.org/api/latest/jvm/stdlib/kotlin.concurrent/…
Blieque

Inoltre, l'esempio dato può essere condensato su una riga se l' Timeroggetto non verrà utilizzato più di una volta, ad es Timer().schedule(timerTask { ... }, 3000). È disponibile anche un'opzione più amichevole per Kotlin; vedi la risposta di jonguer.
Blieque,

10

Un semplice esempio per mostrare un brindisi dopo 3 secondi :

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

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

1
posso cancellare la chiamata?
Eduardo Oliveros,

6

Se stai cercando un uso generico, ecco il mio suggerimento:

Crea una classe denominata come Run:

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

E usa così:

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

Puoi semplificarlo come estensione fucntion
Vlad

@Ogulcan, lamda più kotlinica Run.after(1000) { toRun() }. Ho ragione
binrebin, il

0

Ho consigliato di utilizzare SingleThread perché non è necessario ucciderlo dopo l'uso. Inoltre, il metodo " stop ()" è deprecato nel linguaggio Kotlin.

private fun mDoThisJob(){

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

    }, 1, 1, TimeUnit.SECONDS)
}

Inoltre, puoi usarlo per un lavoro periodico. E 'molto utile. Se desideri fare un lavoro per ogni secondo, puoi impostare perché i suoi parametri:

Executors.newSingleThreadScheduledExecutor (). ScheduleAtFixedRate (comando eseguibile, ritardo iniziale lungo, periodo lungo, unità TimeUnit);

I valori di TimeUnit sono: NANOSECONDI, MICROSECONDI, MILLISECONDI, SECONDI, MINUTI, ORE, GIORNI.

@canerkaseler

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.