Kotlin延迟后如何调用函数?


153

作为标题,是否有任何方法可以在延迟(例如1秒)后调用函数Kotlin

Answers:


134

您可以使用时间表

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

示例(感谢@Nguyen Minh Binh-在此处找到它: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
谢谢!超级容易。在这里找到一个例子jamie.mccrindle.org/2013/02/... Timer("SettingUp", false).schedule(500) { doSomething() }
阮平

9
如果添加了以下两个导入,则它会编译:import java.util.Timer和import kotlin.concurrent.schedule
Customizer

3
@Matias Elorriaga,对我来说,将其放在新的品牌文件中无法编译,甚至添加了导入定制器说
Sulfkain

3
您无需将其放在文件中,该方法是stdlib的一部分,请遵循答案第一行中的链接,
Matias Elorriaga

3
我最初以为即使导入后也不会编译kotlin.concurrent.schedule,因为Kotlin只是抱怨签名不匹配,但是后来我意识到我试图通过Int而不是Long。更正后进行编译。
乔·拉普

178

还有一个使用选项 Handler -> postDelayed

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

18
请补充说,它仅在android上可用,因为该问题要求使用通用的kotlin方法(尽管它确实具有Android标签)
Yoav Sternberg

5
从您的角度来看,这不是建设性的。结果,当用户将搜索android标签时,可能会认为这是错误的答案。
Bogdan Ustyak

9
对于Android,最好使用Handler而不是Timer:stackoverflow.com/questions/20330355/timertask-or-handler
woprandi

我认为,您应该添加代码以在活动/片段完成后删除处理程序。
CoolMind

如果您打算这样做,它将不会在UI线程上运行。
AndroidDev

93

很多方法

1.使用Handler

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

2.使用Timer

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

更短

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

最短的

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

3.使用Executors课堂

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

1
您认为最好的解决方案是什么?
塔米姆·阿塔菲

1
可能第一个使用Handler。请参阅stackoverflow.com/a/40339630/1159930
Markymark

36

您必须导入以下两个库:

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

然后以这种方式使用它:

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

27

您可以创建launch一个协程,delay然后调用该函数:

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

如果您不在类或对象之外,则GlobalScope可以在其中运行协程,否则建议CoroutineScope在周围的类中实现,这样可以在必要时取消与该范围关联的所有协程。


谢谢!奇怪的是,协程仅在2018
。– CoolMind

@coolMind几个月以来一直保持稳定,因此它们很新...
Jonas Wilms

是的,从十月到十一月,但是以前存在过。
CoolMind

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

1
您能解释一下为什么我需要写“ timerTask”而不是花括号吗?
雨果·帕索斯

2
我想你是。Timer.schedule()期望a TimerTask为第一个参数。kotlin.concurrent.timerTask()将给定的lambda包装在TimerTask实例中。看到这里:kotlinlang.org/api/latest/jvm/stdlib/kotlin.concurrent/…–
Blieque

另外,如果该Timer对象不会被多次使用(例如),则可以将给定的示例压缩为一行Timer().schedule(timerTask { ... }, 3000)。也提供了更适合Kotlin的选项;请参阅jonguer的答案。
Blieque

10

一个简单的示例,在3秒后显示敬酒:

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

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

1
我可以取消通话吗?
Eduardo Oliveros

6

如果您正在寻找通用用法,这是我的建议:

创建一个名为的类Run

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

像这样使用:

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

您可以将其简化为扩展功能
Vlad19,19年

@Ogulcan,更多的kotlinic lamda Run.after(1000) { toRun() }。我正确

0

我建议使用SingleThread,因为您不必在使用后将其杀死。同样,Kotlin语言不建议使用“ stop()”方法。

private fun mDoThisJob(){

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

    }, 1, 1, TimeUnit.SECONDS)
}

此外,您可以将其用于定期工作。这是非常有用的。如果您想每秒进行一次工作,则可以进行设置,因为它的参数:

Executors.newSingleThreadScheduledExecutor()。scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit);

TimeUnit值是:NANOSECONDS,MICROSECONDS,MILLISECONDS,SECONDS,MINUTES,HOURS,DAYS。

@canerkaseler

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.