As the title, is there any way to call a function after delay (1 second for example) in Kotlin?
- 22,901
- 30
- 113
- 160
12 Answers
There is also an option to use Handler -> postDelayed
Handler().postDelayed({
//doSomethingHere()
}, 1000)
- 5,125
- 2
- 19
- 16
-
29Please add that it is only available on android, since the question asks for a general kotlin method (although it does have the Android tag) – Yoav Sternberg Apr 20 '17 at 13:43
-
7It's not constructive from your side. As a result when users will search android tag might think that this is wrong answer. – Bogdan Ustyak Apr 20 '17 at 20:27
-
12For Android, it's better to use Handler than Timer : https://stackoverflow.com/questions/20330355/timertask-or-handler – woprandi Apr 20 '18 at 13:54
-
I think, you should add a code for removing handlers after activity/fragment finish. – CoolMind Jan 30 '19 at 07:37
-
1This will not run on the UI thread if you intended on doing that. – Johann Aug 24 '19 at 06:37
-
2In Android, Handler is deprecated. any alternative? – leeCoder Dec 13 '21 at 03:12
-
I think for Android and Kotlin ist Coroutines the best alternative. https://kotlinlang.org/docs/coroutines-overview.html – dudi Dec 13 '21 at 07:32
You can use Schedule
inline fun Timer.schedule(
delay: Long,
crossinline action: TimerTask.() -> Unit
): TimerTask (source)
example (thanks @Nguyen Minh Binh - found it here: 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()
}
- 7,766
- 8
- 46
- 61
- 8,303
- 5
- 38
- 54
-
17Thanks! Super easy. Found an example here http://jamie.mccrindle.org/2013/02/exploring-kotlin-standard-library-part-3.html `Timer("SettingUp", false).schedule(500) { doSomething() }` – Nguyen Minh Binh Apr 11 '17 at 14:35
-
15It does compile, if you add these two imports: import java.util.Timer and import kotlin.concurrent.schedule – Customizer Dec 31 '17 at 00:29
-
3@Matias Elorriaga, for me, putting this on a new brand file doesn't compile, even adding the imports Customizer said – Sulfkain Jan 16 '18 at 09:09
-
3you don't need to put it on a file, that method is part of stdlib, follow the link in the first line of the answer, – Matias Elorriaga Jan 16 '18 at 13:38
-
-
2for those that would like to have it run at an interval: timer.scheduleAtFixedRate(0, inactivityHeartbeat) { //.... do stuff} – Bart Burg Sep 20 '18 at 11:00
-
4I originally thought this wouldn't compile even after importing `kotlin.concurrent.schedule`, because Kotlin merely complained of a signature mismatch, but then I realized I was trying to pass an Int instead of a Long. It compiled after correcting that. – Joe Lapp Apr 30 '19 at 15:19
-
Can someone show this as an example. Cut and pasted this and it does not compile had both imports too. Says the schedule needs a body on the inline function – JPM Jul 18 '19 at 19:46
-
-
Downvoted because it doesn't compile like many of the comments have already indicated. – Johann Aug 24 '19 at 06:35
-
@AndroidDev is part of the standard library, you don’t need to compile, just add the import.. – Matias Elorriaga Aug 24 '19 at 10:56
-
1@IgorGanapolsky - this code compiles fine on Kotlin 1.3.50. What's your error msg? You might have faced my initial problem: make sure the numeric value passed in (500) is a Long and not Int. You'll get a compile error if you do something like: Timer("SettingUp", false).schedule(500+x) {} where "x" is an Int you declared elsewhere. Declare x as a Long and you'll be fine, e.g., val x = 25L – Vahid Pazirandeh Nov 08 '19 at 19:28
-
that work great! Following question is how to insert my class scope inside of this. AKA replace ` doSomething()` with `this.myFunc()`? – Blue Bot Aug 23 '20 at 09:43
-
1
Many Ways
1. Using Handler class
Handler().postDelayed({
TODO("Do something")
}, 2000)
2. Using Timer class
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. Using Executors class
Executors.newSingleThreadScheduledExecutor().schedule({
TODO("Do something")
}, 2, TimeUnit.SECONDS)
- 52,662
- 21
- 188
- 195
-
3
-
2Probably the first one using a Handler. See https://stackoverflow.com/a/40339630/1159930 – Markymark Jan 24 '20 at 18:51
-
Can we do it synchronously , Handler is in Android package I believe. Is there any other way – Akshay Hazari Feb 22 '22 at 06:30
-
@AkshayHazari See his answer.. https://stackoverflow.com/a/52801912/6891563 – Khemraj Sharma Feb 22 '22 at 16:59
-
1Just to follow up on the comment regarding Handler().postDelayed being the best solution... that's deprecated now (at least in Android) and suggests Executors, so at least for Android I'd say that's the "best solution" (though Timer is also simple and straightforward) – anabi Apr 14 '22 at 07:18
You could launch a coroutine, delay it and then call the function:
/*GlobalScope.*/launch {
delay(1000)
yourFn()
}
If you are outside of a class or object prepend GlobalScope to let the coroutine run there, otherwise it is recommended to implement the CoroutineScope in the surrounding class, which allows to cancel all coroutines associated to that scope if necessary.
- 120,546
- 16
- 121
- 140
-
-
@coolMind they are stable since a few months, so they are quite new ... – Jonas Wilms Jan 30 '19 at 09:52
-
val timer = Timer()
timer.schedule(timerTask { nextScreen() }, 3000)
- 997
- 2
- 11
- 23
-
1Can you please explain me why I there's need to write "timerTask" instead of just braces? – Hugo Passos Dec 22 '17 at 07:49
-
3I think you do. `Timer.schedule()` expects a `TimerTask` as it's first argument. `kotlin.concurrent.timerTask()` wraps the given lambda in a `TimerTask` instance. See here: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.concurrent/timer-task.html – Blieque Mar 27 '18 at 17:18
-
Also, the given example can be condensed to one line if the `Timer` object isn't going to be used more than once, e.g., `Timer().schedule(timerTask { ... }, 3000)`. A more Kotlin-friendly option is available too; see jonguer's answer. – Blieque Mar 27 '18 at 17:20
If you are in a fragment with viewModel scope you can use Kotlin coroutines:
myViewModel.viewModelScope.launch {
delay(2000)
// DoSomething()
}
- 553
- 10
- 24
A simple example to show a toast after 3 seconds :
fun onBtnClick() {
val handler = Handler()
handler.postDelayed({ showToast() }, 3000)
}
fun showToast(){
Toast.makeText(context, "Its toast!", Toast.LENGTH_SHORT).show()
}
- 2,302
- 20
- 36
If you're using more recent Android APIs the Handler empty constructor has been deprecated and you should include a Looper. You can easily get one through Looper.getMainLooper().
Handler(Looper.getMainLooper()).postDelayed({
//Your code
}, 2000) //millis
- 5,018
- 5
- 30
- 48
If you are looking for generic usage, here is my suggestion:
Create a class named as Run:
class Run {
companion object {
fun after(delay: Long, process: () -> Unit) {
Handler().postDelayed({
process()
}, delay)
}
}
}
And use like this:
Run.after(1000, {
// print something useful etc.
})
- 4,990
- 6
- 32
- 48
-
1
-
1@Ogulcan, more kotlinic lamda `Run.after(1000) { toRun() }`. Am I correct – binrebin Jul 15 '20 at 10:00
i suggest to use kotlin coroutine and if you want to cancel it. its simple and light weight.
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()
- 362
- 2
- 8
I recommended using SingleThread because you do not have to kill it after using. Also, "stop()" method is deprecated in Kotlin language.
private fun mDoThisJob(){
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate({
//TODO: You can write your periodical job here..!
}, 1, 1, TimeUnit.SECONDS)
}
Moreover, you can use it for periodical job. It is very useful. If you would like to do job for each second, you can set because parameters of it:
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);
TimeUnit values are: NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS.