Как вызвать функцию после задержки в Kotlin?
Как заголовок, есть ли способ вызвать функцию после задержки (например, 1 секунда) в Kotlin
?
15 ответов
Вы можете использовать Расписание
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)
Timer("SettingUp", false).schedule(500) {
doSomething()
}
Также есть возможность использовать Handler -> postDelayed
Handler().postDelayed({
//doSomethingHere()
}, 1000)
Много способов
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)
Вы могли бы launch
сопрограмма, delay
это, а затем вызвать функцию:
launch {
delay(1000)
yourFn()
}
Вы должны импортировать следующие две библиотеки:
import java.util.*
import kotlin.concurrent.schedule
и после этого используйте его следующим образом:
Timer().schedule(10000){
//do something
}
val timer = Timer()
timer.schedule(timerTask { nextScreen() }, 3000)
Если вы используете более свежие API-интерфейсы Android, пустой конструктор Handler устарел, и вы должны включить Looper. Вы можете легко пройти черезLooper.getMainLooper()
.
Handler(Looper.getMainLooper()).postDelayed({
//Your code
}, 2000) //millis
Если вы находитесь во фрагменте с областью видимости viewModel, вы можете использовать сопрограммы Kotlin:
myViewModel.viewModelScope.launch {
delay(2000)
// DoSomething()
}
Простой пример показа тоста через 3 секунды:
fun onBtnClick() {
val handler = Handler()
handler.postDelayed({ showToast() }, 3000)
}
fun showToast(){
Toast.makeText(context, "Its toast!", Toast.LENGTH_SHORT).show()
}
Если вы ищете универсальное использование, вот мое предложение:
Создать класс с именем как Run
:
class Run {
companion object {
fun after(delay: Long, process: () -> Unit) {
Handler().postDelayed({
process()
}, delay)
}
}
}
И используйте так:
Run.after(1000, {
// print something useful etc.
})
Я предлагаю использовать корутину 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()
Другой способ создать избыточное задание, отличный от этого ; это не требует приостановки функции.
val repeatableJob = CoroutineScope(Dispatchers.IO).launch {
while (true) {
delay(1000)
}
}
Отменить, когда вы закончите -repeatableJob.cancel()
Я рекомендовал использовать SingleThread, потому что вам не нужно его убивать после использования. Кроме того, в языке Котлин устарел методstop().
private fun mDoThisJob(){
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate({
//TODO: You can write your periodical job here..!
}, 1, 1, TimeUnit.SECONDS)
}
Более того, вы можете использовать его для периодической работы. Это очень полезно. Если вы хотите выполнять задание каждую секунду, вы можете установить его параметры:
Executors.newSingleThreadScheduledExecutor(). ScheduleAtFixedRate(команда Runnable, длинная начальная задержка, длительный период, единица TimeUnit);
Значения TimeUnit: НС, МИКРОСЕКУНД, МИЛЛИСЕКУНД, СЕКУНД, МИНУТЫ, ЧАСЫ, ДНИ.
@canerkaseler
Я использую следующие функции:
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())
}
если вы вызываете функцию в пользовательском интерфейсе.
Timer().schedule(1000) {
activity?.runOnUiThread {
doSomething()
}
}