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.