【问题标题】:Kotlin Multiplatform: sharing actual class implementation for multiple targets (iOS, macOS)Kotlin Multiplatform:共享多个目标(iOS、macOS)的实际类实现
【发布时间】:2019-11-07 16:36:55
【问题描述】:

我正在开发一个支持 JVM、iOS 和 macOS 的 Kotlin/Native 多平台项目。我的设置有以下模块:

- common
- ios
- jvm
- macos

我想使用一些本机代码作为actual 类并将expected 类放入common。但是,对于多个目标(iOS 和 macOS),实际的类实现是相同的。有没有办法设置我的源(可能在 Gradle 中),这样我就不必维护 2 个相同的实际课程副本?

【问题讨论】:

  • 您能否扩展此“但是,每个目标(iOS、JVM 和 MacOS)的实际类实现都是相同的”。如果它们是相同的,你为什么要做期望/实际?我可以看到 iOS 和 MacOS 是一样的,但三者都是?
  • @KevinGalligan 进行了澄清编辑。你是对的,iOS 和 macOS 是一样的,但 JVM 是不同的。

标签: intellij-idea kotlin kotlin-multiplatform kotlin-native


【解决方案1】:

Stately 有一个相当复杂的配置。 iOS 和 Macos 共享所有相同的代码。

要构建项目,有commonMainnativeCommonMain 依赖于它,实际上appleMain 依赖于nativeCommonMain

commonMain {
    dependencies {
        implementation 'org.jetbrains.kotlin:kotlin-stdlib-common'
    }
}

jvmMain {
    dependsOn commonMain
    dependencies {
        implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
    }
}

nativeCommonMain {
    dependsOn commonMain
}

appleMain {
    dependsOn nativeCommonMain
}

configure([iosX64Main, iosArm64Main, macosMain, iosArm32Main]) {
    dependsOn appleMain
}

这种结构可能比您需要的更深,但我们需要一些不同的 linux 和 windows 结构。我认为 Egor 上面的回答更容易理解。

我们实际上在 Stately 中定义了多平台原子,因此您可以将它们用作灵感,或者实际上只是使用库本身。

https://github.com/touchlab/Stately

常见

expect class AtomicInt(initialValue: Int) {
  fun get(): Int
  fun set(newValue: Int)
  fun incrementAndGet(): Int
  fun decrementAndGet(): Int

  fun addAndGet(delta: Int): Int
  fun compareAndSet(expected: Int, new: Int): Boolean
}

JVM

actual typealias AtomicInt = AtomicInteger

原生

actual class AtomicInt actual constructor(initialValue:Int){
  private val atom = AtomicInt(initialValue)

  actual fun get(): Int = atom.value

  actual fun set(newValue: Int) {
    atom.value = newValue
  }

  actual fun incrementAndGet(): Int = atom.addAndGet(1)

  actual fun decrementAndGet(): Int = atom.addAndGet(-1)

  actual fun addAndGet(delta: Int): Int = atom.addAndGet(delta)

  actual fun compareAndSet(expected: Int, new: Int): Boolean = atom.compareAndSet(expected, new)

}

【讨论】:

    【解决方案2】:

    Okio 中,我们声明了两个额外的源集nativeMainnativeTest,并将内置的原生源集配置为依赖它们:

    apply plugin: 'org.jetbrains.kotlin.multiplatform'
    
    kotlin {
      iosX64()
      iosArm64()
      linuxX64()
      macosX64()
      mingwX64('winX64')
      sourceSets {
        nativeMain {
          dependsOn commonMain
        }
        nativeTest {
          dependsOn commonTest
        }
    
        configure([iosX64Main, iosArm64Main, linuxX64Main, macosX64Main, winX64Main]) {
          dependsOn nativeMain
        }
        configure([iosX64Test, iosArm64Test, linuxX64Test, macosX64Test, winX64Test]) {
          dependsOn nativeTest
        }
      }
    }
    

    【讨论】:

      【解决方案3】:

      如果所有三个实现都相同,只需将该代码放入commonexpect/actual 仅用于在不同平台上不同的事物

      【讨论】:

      • 我最初说错了。我的意思是说 iOS 和 macOS 的目标实现是相同的。 JVM是不同的。我想使用一个原子整数,我可以将 AtomicInt 用于 iOS 和 macOS,但需要将 AtomicInteger 用于 JVM
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-16
      • 1970-01-01
      • 2021-11-25
      相关资源
      最近更新 更多