Невозможно получить доступ к fixedRateTimer в мультиплатформе Kotlin

Я работаю над мультиплатформенным проектом Kotlin. И я пытаюсь использовать таймер и таймер обратного отсчета, но не могу получить доступ к kotlin.concurrent.fixedRateTimer или import kotlin.concurrent.timer в модуле commonMain.

введите описание изображения здесь

Однако kotlin.concurrent доступен:  введите описание изображения здесь

Это 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")
                //...
            }
        }
        //...
    }
}

Интересно, можно ли вообще там использовать эти методы. Если нет, как мне написать таймер и таймер обратного отсчета в модуле 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()
    }

person Amir    schedule 21.10.2020    source источник


Ответы (2)


Как сказал Qaz, функция, которую вы пытаетесь использовать в общем коде, - это Только JVM.

Обычно в KMP, когда у вас все еще нет общей функциональности, уже встроенной в фреймворк, вы можете использовать разные подходы:

  1. Используйте другую библиотеку (например, moko-time). Лучшее место для поиска библиотек - здесь.
  2. Используйте собственные классы framworks с помощью механизма _1 _ / _ 2_

Просто чтобы дать вам и пример того, что можно сделать (не уверен, подходит ли это вам или может соответствовать вашим потребностям. Просто чтобы направить вас в правильном направлении, и, прежде всего, то, что я написал, вообще не может быть готово к производству. [-;)

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
    }
}
person shadowsheep    schedule 22.10.2020

Функция, которую вы пытаетесь использовать, - это только JVM. См. https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.concurrent/fixed-rate-timer.html

person Qaz    schedule 21.10.2020
comment
Как я могу добиться там такой же функциональности? - person Amir; 21.10.2020