I'm working on a Kotlin Multiplatform project. And I'm trying to use a timer and countdown timer but I cannot access kotlin.concurrent.fixedRateTimer
or import kotlin.concurrent.timer
in commonMain
module.
However the kotlin.concurrent
is available:
This is root build.gradle
:
plugins {
kotlin("multiplatform")
id("com.android.library")
id("kotlin-android-extensions")
}
// ...
kotlin {
//...
sourceSets {
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.4.10")
implementation("org.jetbrains.kotlin:kotlin-reflect:1.4.10")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9")
//...
}
}
//...
}
}
I wonder if it's even possible to use these methods there. If not, how can I write a timer and countdown timer in commonMain
module?
I have tried to use Coroutines
to achieve the same functionality but failed because they are not precise:
fun doAfter(delay: Long, action: () -> (Unit)) = launch {
delay(delay)
action.invoke()
}
fun countdown(time: Long, tick: Long, onTick: () -> (Unit), onFinish: () -> (Unit)) = launch {
val ticks = (time / tick).toInt()
repeat(ticks) {
onTick()
delay(tick)
}
onFinish()
}
As said by Qaz, the function you are trying to use in common code is JVM only.
Usually in KMP, when you still don't have a common functionality already built in by the framework you could follow different approaches:
expect
/actual
mechanismJust to give you and example of what could be done (not sure if that is right for you or could fit your needs. It's just to put you in the right direction and above all what I've wrote could not be production ready at all [-;)
commonMain:Timer.kt
expect class KMMTimer(
name: String? = null,
interval: Long,
delay: Long,
action: () -> Unit
) {
val name: String?
val interval: Long
val delay: Long
fun start()
fun cancel()
fun isRunning(): Boolean
}
androidMain:Timer.kt
import java.util.*
import kotlin.concurrent.fixedRateTimer
actual class KMMTimer actual constructor(
actual val name: String?,
actual val interval: Long,
actual val delay: Long,
action: () -> Unit
) {
private var timer: Timer? = null
private val action = action
actual fun start() {
if (!isRunning()) {
timer = fixedRateTimer(
name = name,
initialDelay = delay,
period = interval
) {
action()
}
}
}
actual fun cancel() {
timer?.cancel()
timer = null
}
actual fun isRunning(): Boolean {
return timer != null
}
}
iosMain:Timer.kt
import platform.Foundation.NSDate
import platform.Foundation.NSRunLoop
import platform.Foundation.NSRunLoopCommonModes
import platform.Foundation.NSTimer
actual class KMMTimer actual constructor(
actual val name: String?,
actual val interval: Long,
actual val delay: Long,
action: () -> Unit
) {
private var timer: NSTimer? = null
private var action = action
actual fun start() {
if (!isRunning()) {
timer = NSTimer(
fireDate = NSDate(
NSDate().timeIntervalSinceReferenceDate + (delay.toDouble() / 1000)
),
interval = (interval.toDouble() / 1000),
repeats = true,
block = {
action()
}
)
timer?.let {
NSRunLoop.currentRunLoop().addTimer(it, NSRunLoopCommonModes)
}
}
}
actual fun cancel() {
timer?.invalidate()
timer = null
}
actual fun isRunning(): Boolean {
return timer != null
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With