Kotlin Multiplatform:为多个目标(iOS,macOS)共享实际的类实现

时间:2019-06-25 19:30:03

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

我正在研究一个支持JVM,iOS和macOS的Kotlin / Native Multiplatform项目。我的设置包含以下模块:

- common
- ios
- jvm
- macos

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

3 个答案:

答案 0 :(得分:3)

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)

}

答案 1 :(得分: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
    }
  }
}

答案 2 :(得分:0)

如果所有三个实现都是相同的,只需将代码放在common中。 expect/actual仅用于在不同平台上不同的事物