无法在Kotlin多平台中访问fixedRateTimer

时间:2020-10-21 06:54:21

标签: kotlin kotlin-multiplatform

我正在研究Kotlin Multiplatform项目。而且我正在尝试使用计时器和倒数计时器,但无法访问kotlin.concurrent.fixedRateTimer模块中的import kotlin.concurrent.timercommonMain

enter image description here

但是kotlin.concurrent可用: enter image description here

这是根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")
                //...
            }
        }
        //...
    }
}

我想知道是否甚至可以在那里使用这些方法。如果没有,如何在commonMain模块中编写计时器和倒数计时器?

我尝试使用Coroutines来实现相同的功能,但是由于它们不精确而失败了:

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

2 个答案:

答案 0 :(得分:3)

答案 1 :(得分:3)

正如Qaz所说,您尝试在通用代码中使用的函数是JVM only

通常在KMP中,当您仍然没有框架内置的通用功能时,可以采用不同的方法:

  1. 使用其他人的图书馆(例如moko-time)-搜索图书馆的最佳位置是here
  2. 通过expect/actual机制使用本地framworks类

仅举例说明可以做些什么(不确定是否适合您或满足您的需求。这只是为了使您处于正确的方向,而我写的所有内容都不能用于生产。完全准备就绪[-;)

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