¿Cómo llamar a una función después de un retraso en Kotlin?


154

Como título, ¿hay alguna forma de llamar a una función después del retraso (1 segundo, por ejemplo) Kotlin?

Respuestas:


134

Puedes usar Schedule

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

ejemplo (gracias @Nguyen Minh Binh - lo encontré aquí: 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
¡Gracias! Muy facil. Encontré un ejemplo aquí jamie.mccrindle.org/2013/02/… Timer("SettingUp", false).schedule(500) { doSomething() }
Nguyen Minh Binh

9
Se compila si agrega estas dos importaciones: import java.util.Timer e import kotlin.concurrent.schedule
Personalizador

3
@Matias Elorriaga, para mí, poner esto en un nuevo archivo de marca no se compila, incluso agregando las importaciones, dijo el Personalizador
Sulfkain

3
no necesita ponerlo en un archivo, ese método es parte de stdlib, siga el enlace en la primera línea de la respuesta,
Matias Elorriaga

3
Originalmente pensé que esto no se compilaría incluso después de la importación kotlin.concurrent.schedule, porque Kotlin simplemente se quejó de una falta de coincidencia de firma, pero luego me di cuenta de que estaba tratando de pasar un Int en lugar de un Long. Se compiló después de corregir eso.
Joe Lapp

178

También hay una opción para usar Handler -> postDelayed

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

18
Agregue que solo está disponible en Android, ya que la pregunta solicita un método general de kotlin (aunque tiene la etiqueta de Android)
Yoav Sternberg

55
No es constructivo de tu lado. Como resultado, cuando los usuarios busquen en la etiqueta de Android, podría pensar que esta es una respuesta incorrecta.
Bogdan Ustyak

9
Para Android, es mejor usar Handler que Timer: stackoverflow.com/questions/20330355/timertask-or-handler
woprandi

Creo que debería agregar un código para eliminar los controladores después de que finalice la actividad / fragmento.
CoolMind

Esto no se ejecutará en el hilo de la interfaz de usuario si pretendía hacerlo.
AndroidDev

93

Muchas maneras

1. Usando la Handlerclase

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

2. Usando la Timerclase

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

Corta

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

Mas corto

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

3. Usando la Executorsclase

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

1
¿Cuál crees que es la mejor solución aquí?
Tamim Attafi

1
Probablemente el primero que usa un controlador. Ver stackoverflow.com/a/40339630/1159930
Markymark

36

Debe importar las siguientes dos bibliotecas:

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

y después de eso úsalo de esta manera:

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

27

Podrías launchuna corutina, delayy luego llamar a la función:

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

Si está fuera de una clase o un objeto, GlobalScopehaga que la corutina se ejecute allí; de lo contrario, se recomienda implementarla CoroutineScopeen la clase circundante, lo que permite cancelar todas las corutinas asociadas a ese alcance si es necesario.


¡Gracias! Extraño, esas corutinas se mencionaron solo en 2018.
CoolMind

@coolMind son estables desde hace unos meses, por lo que son bastante nuevos ...
Jonas Wilms

Sí, de octubre a noviembre, pero existía antes.
CoolMind

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

1
¿Puede explicarme por qué necesito escribir "timerTask" en lugar de solo llaves?
Hugo Passos

2
Creo que lo haces. Timer.schedule()espera un TimerTaskcomo su primer argumento. kotlin.concurrent.timerTask()envuelve el lambda dado en una TimerTaskinstancia. Ver aquí: kotlinlang.org/api/latest/jvm/stdlib/kotlin.concurrent/…
Blieque

También, el ejemplo dado se puede condensar a una línea si el Timerobjeto no se va a utilizar más de una vez, por ejemplo, Timer().schedule(timerTask { ... }, 3000). También está disponible una opción más amigable para Kotlin; ver la respuesta de jonguer.
Blieque

10

Un ejemplo simple para mostrar un brindis después de 3 segundos :

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

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

1
¿Puedo cancelar la llamada?
Eduardo Oliveros

6

Si está buscando un uso genérico, aquí está mi sugerencia:

Crea una clase llamada como Run:

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

Y use así:

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

Puede simplificar esto como función de extensión
Vlad

@Ogulcan, más kotlinic lamda Run.after(1000) { toRun() }. ¿Estoy en lo cierto?
binrebin

0

Le recomendé usar SingleThread porque no tiene que matarlo después de usarlo. Además, el método " stop ()" está en desuso en el lenguaje Kotlin.

private fun mDoThisJob(){

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

    }, 1, 1, TimeUnit.SECONDS)
}

Además, puede usarlo para trabajos periódicos. Es muy útil. Si desea hacer un trabajo por cada segundo, puede configurarlo porque los parámetros de la misma:

Executors.newSingleThreadScheduledExecutor (). ScheduleAtFixedRate (comando Runnable, long initialDelay, long period, TimeUnit unit);

Los valores de TimeUnit son: NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS.

@canerkaseler

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.