Como chamar uma função após atraso no Kotlin?


154

Como o título, existe alguma maneira de chamar uma função após um atraso (1 segundo por exemplo) em Kotlin?

Respostas:


134

Você pode usar o Schedule

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

exemplo (obrigado @Nguyen Minh Binh - encontre-o aqui: 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
Obrigado! Super fácil. Encontre um exemplo aqui jamie.mccrindle.org/2013/02/… Timer("SettingUp", false).schedule(500) { doSomething() }
Nguyen Minh Binh

9
Ele é compilado, se você incluir essas duas importações: import java.util.Timer e import kotlin.concurrent.schedule
Customizer

3
@Matias Elorriaga, para mim, colocar isso em um novo arquivo de marca não compilar, mesmo adicionando as importações Customizer disse
Sulfkain

3
você não precisa colocá-lo em um arquivo, esse método faz parte do stdlib, siga o link na primeira linha da resposta,
Matias Elorriaga

3
Originalmente, pensei que isso não seria compilado mesmo após a importação kotlin.concurrent.schedule, porque Kotlin apenas reclamou de uma incompatibilidade de assinatura, mas então percebi que estava tentando passar um Int em vez de um Long. Compilou depois de corrigir isso.
precisa

178

Há também uma opção para usar Handler -> postDelayed

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

18
Por favor, adicione que é apenas disponível no Android, já que a questão pede um método Kotlin geral (embora não têm a marca Android)
Yoav Sternberg

5
Não é construtivo do seu lado. Como resultado, quando os usuários pesquisam a tag android, podem pensar que esta é uma resposta errada.
precisa saber é o seguinte

9
Para Android, é melhor usar Handler de Timer: stackoverflow.com/questions/20330355/timertask-or-handler
woprandi

Eu acho que você deve adicionar um código para remover manipuladores após o término da atividade / fragmento.
precisa saber é o seguinte

Isso não será executado no thread da interface do usuário se você pretender fazer isso.
AndroidDev 24/08/19

93

Várias maneiras

1. Usando Handlerclasse

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

2. Usando Timerclasse

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

Mais curta

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

Mais curto

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

3. Usando Executorsclasse

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

1
e qual você acha que é a melhor solução aqui?
Tamim Attafi 29/11/19

1
Provavelmente o primeiro usando um manipulador. Veja stackoverflow.com/a/40339630/1159930
Markymark

36

Você precisa importar as duas bibliotecas a seguir:

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

e depois disso use-o desta maneira:

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

27

Você poderia launchuma corotina, delaye depois chamar a função:

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

Se você estiver fora de uma classe ou objeto antes GlobalScopede permitir que a corotina seja executada lá, caso contrário, é recomendável implementar a CoroutineScopeclasse circundante, o que permite cancelar todas as corotinas associadas a esse escopo, se necessário.


Obrigado! Estranho, que co-rotinas foram mencionados apenas em 2018.
CoolMind

@coolMind eles são estáveis desde há alguns meses, então eles são muito novo ...
Jonas Wilms

Sim, de outubro a novembro, mas já existia antes.
precisa saber é o seguinte

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

1
Você pode me explicar por que preciso escrever "timerTask" em vez de apenas chaves?
Hugo Passos

2
Eu acho que você faz. Timer.schedule()espera um TimerTaskcomo é o primeiro argumento. kotlin.concurrent.timerTask()agrupa o lambda fornecido em uma TimerTaskinstância. Veja aqui: kotlinlang.org/api/latest/jvm/stdlib/kotlin.concurrent/…
Blieque

Além disso, o exemplo dado pode ser condensado em uma linha se o Timerobjeto não for usado mais de uma vez, por exemplo Timer().schedule(timerTask { ... }, 3000),. Uma opção mais amigável para Kotlin também está disponível; veja a resposta do jonguer.
Blieque 27/03

10

Um exemplo simples para mostrar um brinde após 3 segundos :

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

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

1
posso cancelar a ligação?
Eduardo Oliveros

6

Se você estiver procurando por uso genérico, aqui está minha sugestão:

Crie uma classe chamada como Run:

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

E use assim:

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

Você pode simplificar isso como extensão fucntion
Vlad

@Ogulcan, mais lamina kotlinic Run.after(1000) { toRun() }. Estou correto
binrebin 15/07

0

Eu recomendei o uso do SingleThread porque você não precisa matá-lo após o uso. Além disso, o método " stop ()" foi descontinuado no idioma Kotlin.

private fun mDoThisJob(){

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

    }, 1, 1, TimeUnit.SECONDS)
}

Além disso, você pode usá-lo para trabalhos periódicos. É muito útil. Se você deseja fazer o trabalho a cada segundo, é possível definir os parâmetros:

Executors.newSingleThreadScheduledExecutor (). ScheduleAtFixedRate (comando Runnable, long initialDelay, longo período, unidade TimeUnit);

Os valores de TimeUnit são: NANOSECONDS, MICROSECONDS, MILISECONDS, SECONDS, MINUTES, HOURS, DIAS.

@canerkaseler

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.