KMM项目commonMain模块无法通过Okio访问FileSystem.SYSTEM
KMM中commonMain无法访问Okio的FileSystem.SYSTEM问题解答
问题描述
通过Android Studio向导创建面向Android和iOS的Kotlin多平台应用,在shared/build.gradle.kts的commonMain模块添加Okio 3.3.0依赖后,发现commonMain中无法访问FileSystem.SYSTEM(提示“Unresolved Reference: SYSTEM”),但androidMain和iosMain模块可正常访问。疑问如下:
- 这是预期行为吗?
- 是否需要为所有Okio API编写expected/actual映射?
- 有没有其他解决办法或配置调整方式?
核心配置片段
// shared/build.gradle.kts 中的sourceSets部分 sourceSets { val okio = "3.3.0" val commonMain by getting { dependencies { implementation("com.squareup.okio:okio:$okio") } } // ...其他sourceSet配置 }
commonMain代码示例
package de.pixel.kmmpodstryout import okio.FileSystem import okio.Path.Companion.toPath class Greeting { private val platform: Platform = getPlatform() fun greet(): String { val path = "helloworld.txt".toPath() FileSystem.SYSTEM // 此处提示Unresolved Reference SYSTEM return "Hello, ${platform.name} ${readFile()}!" } }
解答
1. 这是预期行为
Okio的FileSystem.SYSTEM是平台专属的具体实现,而commonMain是跨平台通用代码层,仅包含所有平台兼容的抽象API,因此无法直接访问平台相关的具体实例。这是KMM多平台架构的设计逻辑,确保通用层代码的跨平台可移植性。
2. 无需为所有Okio API编写映射
只需要为平台相关的实例(比如FileSystem.SYSTEM)编写简单的expected/actual映射即可,Okio的核心API(如文件读写方法、Path类等)已在common层提供抽象,可直接使用。
3. 具体解决步骤
步骤1:在commonMain定义预期声明
// commonMain下新增或在现有类中添加 expect val systemFileSystem: FileSystem
步骤2:在平台模块添加实际实现
- androidMain:
actual val systemFileSystem: FileSystem = FileSystem.SYSTEM
- iosMain:
actual val systemFileSystem: FileSystem = FileSystem.SYSTEM
步骤3:在commonMain中使用映射后的实例
修改原代码,用systemFileSystem替代FileSystem.SYSTEM:
fun greet(): String { val path = "helloworld.txt".toPath() // 使用映射后的实例执行文件操作 systemFileSystem.read(path) { /* 读写逻辑 */ } return "Hello, ${platform.name}!" }
4. 其他注意事项
- 当前的Okio依赖配置是正确的,Okio 3.x原生支持KMM多平台,无需额外添加依赖。
- 如果不想编写expected/actual,也可以将文件操作逻辑封装到平台模块,common层通过接口调用,但这种方式会导致业务逻辑分散,不如映射方式简洁可控。
内容的提问来源于stack exchange,提问作者Sven
相关产品推荐
相关产品推荐

