0

我正在开发一个 KMM 应用程序,我尝试分别使用 SQLDelight 和 Ktor 实现常规的 localDatasource 和 remoteDatasource。

当我尝试将 AndroidApp 和 iosMain 的本机代码共享到 commonModule 时,我的问题就出现了。我开始在我的 commonModule 期望类中出现以下错误:

Expected function 'cache' has no actual declaration in module KMM-APP.shared for JVM
Expected function 'cache' has no actual declaration in module KMM-APP.shared.iosArm64Main for Native
Expected function 'cache' has no actual declaration in module KMM-APP.shared.iosX64Main for Native

这有点令人困惑,为了我不在我的项目中使用 jvm 模块,尽管我为 IOS 模块使用。

这是我的 AndroidApp 模块的 cacheAndroid.kt :

import android.content.Context
import com.example.kmp_app.db.PetsDatabase
import com.squareup.sqldelight.android.AndroidSqliteDriver

lateinit var appContext: Context

internal actual fun cache(): PetsDatabase {
  val driver = AndroidSqliteDriver(PetsDatabase.Schema, appContext, "petsDB.db")
  return PetsDatabase(driver)
}

这是我的 IOS 模块的类:

import com.example.kmp_app.db.PetsDatabase
import com.squareup.sqldelight.drivers.native.NativeSqliteDriver

internal actual fun cache(): PetsDatabase {
    val driver = NativeSqliteDriver(PetsDatabase.Schema, "petsDB.db")
    return PetsDatabase(driver)
}

以及commonModule的使用:

internal expect fun cache(): PetsDatabase

我在最后一行代码中收到了上面的错误,但我也将错误放入 Android 和 IOS 模块的实际类中,放入它们的期望类变体中。

最后关于我的 build.gradle(common)

plugins {
    kotlin("multiplatform")
    kotlin("native.cocoapods")
    id("com.android.library")
    id("kotlinx-serialization")
    id("com.squareup.sqldelight")
}

version = "1.0"

kotlin {
    targets{
        ios {
            binaries {
                framework {
                    baseName = "shared"
                }
            }
        }
        // Block from https://github.com/cashapp/sqldelight/issues/2044#issuecomment-721299517.
        val onPhone = System.getenv("SDK_NAME")?.startsWith("iphoneos") ?: false
        if (onPhone) {
            iosArm64("ios")
        } else {
            iosX64("ios")
        }

        android()
        //iosSimulatorArm64() sure all ios dependencies support this target
    }

    cocoapods {
        summary = "Some description for the Shared Module"
        homepage = "Link to the Shared Module homepage"
        ios.deploymentTarget = "14.1"
        podfile = project.file("../iosApp/Podfile")
    }
    
    sourceSets {
        all {
            languageSettings.apply {
                useExperimentalAnnotation("kotlinx.coroutines.ExperimentalCoroutinesApi")
            }
        }

        val commonMain by getting{
            dependencies {
                implementation(kotlin("stdlib-common"))
                implementation(Coroutines.Core.core)
                implementation(Ktor.Core.common)
                implementation(Ktor.Json.common)
                implementation(Ktor.Logging.common)
                implementation(Ktor.Serialization.common)
                implementation(SqlDelight.runtime)

            }
        }
        val commonTest by getting {
            dependencies {
                implementation(kotlin("test-common"))
                implementation(kotlin("test-annotations-common"))
                implementation(Ktor.Mock.common)
            }
        }
        val androidMain by getting{
            dependencies {
                implementation(kotlin("stdlib"))
                implementation(Coroutines.Core.core)
                implementation(Ktor.android)
                implementation(Ktor.Core.jvm)
                implementation(Ktor.Json.jvm)
                implementation(Ktor.Logging.jvm)
                implementation(Ktor.Logging.slf4j)
                implementation(Ktor.Mock.jvm)
                implementation(Ktor.Serialization.jvm)
                implementation(Serialization.core)
                implementation(SqlDelight.android)
            }
        }

        val androidAndroidTestRelease by getting
        val androidTest by getting {
            dependsOn(androidAndroidTestRelease)
            dependencies {
                implementation(kotlin("test-junit"))
                implementation("junit:junit:4.13.2")
            }
        }
        val iosX64Main by getting
        val iosArm64Main by getting
        //val iosSimulatorArm64Main by getting
        val ios by creating {
            dependsOn(commonMain)
            iosX64Main.dependsOn(this)
            iosArm64Main.dependsOn(this)
            //iosSimulatorArm64Main.dependsOn(this)
            dependencies {
                implementation(SqlDelight.native)
            }
        }
    }
}

android {
    compileSdk = 31
    sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
    defaultConfig {
        minSdk = 21
        targetSdk = 31
        versionCode = 1
        versionName = "1.0"
    }
}
sqldelight {
    database("PetsDatabase") {
        packageName = "com.example.kmp_app.db"
        sourceFolders = listOf("sqldelight")
    }
}

还有我的项目 build.gradle:

buildscript {
    repositories {
        google()
        mavenCentral()
        jcenter()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:4.2.0")
        classpath(kotlin("gradle-plugin", version = Versions.kotlin))
        classpath(kotlin("serialization", version = Versions.kotlin))
        classpath("com.squareup.sqldelight:gradle-plugin:${Versions.sqldelight}")
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
        jcenter()
    }
}

plugins{
    //kotlin("android") version "${Versions.kotlin}" apply false
}

我希望你能提供帮助,如果这样,请提前感谢!

4

1 回答 1

1

我认为它与packageName你的 Gradle 相关:

 packageName = "com.example.kmp_app.db"
  1. 尝试传递你的缓存函数的路由,而不是"com.example.kmp_app.db" 喜欢如果我的缓存函数存在于dataSource.cacheSource,我们将通过"com.example.kmp_app.db.dataSource.cacheSource"

  2. 确保您的 Cache 实际/期望函数具有相同的包名称,如下所示"com.example.kmp_app.db.dataSource.cacheSource"

共享 gradle

sqldelight {
    database("RecipeDatabase") {
        packageName = "com.example.food1fork.Food1ForkKmm.DataSource.cacheSource"
        sourceFolders = listOf("SqlDelight")
    }
}

iOS 模块

package com.example.food1fork.Food1ForkKmm.DataSource.cacheSource

actual class DriverFactory {
    actual fun createDriver(): SqlDriver {
        return NativeSqliteDriver(RecipeDatabase.Schema, "recipes.db")
    }
}

安卓模块

package com.example.food1fork.Food1ForkKmm.DataSource.cacheSource

actual class DriverFactory(private val context: Context) {
    actual fun createDriver(): SqlDriver {
        return AndroidSqliteDriver(RecipeDatabase.Schema, context, "recipes.db")
    }
}

共享模块

package com.example.food1fork.Food1ForkKmm.DataSource.cacheSource

expect class DriverFactory {
    fun createDriver(): SqlDriver
}
于 2022-02-26T10:56:45.363 回答