如何在Kotlin延迟后调用函数?

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

274499 次浏览

你可以使用时间表

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()
}

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

 Handler().postDelayed({
//doSomethingHere()
}, 1000)
val timer = Timer()
timer.schedule(timerTask { nextScreen() }, 3000)

下面是一个简单的例子,在3秒之后显示toast:

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


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

需要导入以下两个库:

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

然后这样使用它:

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

如果你在寻找通用用法,下面是我的建议:

创建一个名为Run的类:

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

像这样使用:

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

你可以launch一个协程,delay它,然后调用函数:

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

如果你在一个类或对象的外部,预先GlobalScope让协程在那里运行,否则建议在周围的类中实现CoroutineScope,这允许在必要时取消与该作用域关联的所有协程。

很多方面

1. 使用Handler

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

2. 使用Timer

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


// Shorter


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




// Shortest


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

3.使用Executors

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

我建议使用SingleThread,因为你不需要在使用后杀死它。此外,“停止()“;方法在Kotlin语言中已弃用。

private fun mDoThisJob(){


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


}, 1, 1, TimeUnit.SECONDS)
}

此外,您可以使用它定期工作。它非常有用。如果你想在每一秒内完成一个任务,你可以设置它的参数:

Executors.newSingleThreadScheduledExecutor()。scheduleAtFixedRate(可运行命令,长initialDelay,长周期,TimeUnit unit);

时间单位值是:纳秒,微秒,毫秒,秒,分钟,小时,天。

如果你正在使用最新的Android api, Handler空构造函数已经被弃用,你应该包括一个循环程序。你可以很容易地通过Looper.getMainLooper()得到一个。

    Handler(Looper.getMainLooper()).postDelayed({
//Your code
}, 2000) //millis

如果你在一个带有viewModel作用域的片段中,你可以使用Kotlin协程:

    myViewModel.viewModelScope.launch {
delay(2000)
// DoSomething()
}

我建议使用kotlin协程,如果你想取消它。它结构简单,重量轻。

fun repeatFun(): Job {
return coroutineScope.launch {
while(isActive) {
//do your work here
delay(1000)
}
}
}


//start the loop
val repeatFun = repeatRequest()


//Cancel the loop
repeatFun.cancel()

我使用以下函数:

fun <T> delayedAsyncTask(delayMs: Long = 0, task: () -> T): ScheduledFuture<T> {
return Executors
.newSingleThreadScheduledExecutor()
.schedule(Callable<T> { task() }, delayMs, TimeUnit.MILLISECONDS)
}


fun <T> asyncTask(task: () -> T) = delayedAsyncTask(0, task)

这是一个延迟函数的单元测试。当然,使用返回的将来是可选的。

    @Test
fun `delayed task work correctly`() {
val future = delayedAsyncTask(1000) {
"lambda returns hello world"
}
assertEquals(false, future.isDone)
Thread.sleep(1100)
assertEquals(true, future.isDone)
assertEquals("lambda returns hello world", future.get())
}