mcpField
K
kotlin-multiplatform

kotlin-multiplatform

github.com/travisjneuman开发107180 次安装1 天前更新
代码仓库

关于 kotlin-multiplatform

kotlin-multiplatform 是面向 Kotlin 多平台项目开发的技能指南,供需要在 Android、iOS、桌面和 Web 之间共享业务逻辑的开发者使用。内容涉及项目结构、平台实现、网络、存储、界面集成和测试。

主要功能

  1. 01多平台项目结构示例
  2. 02expect/actual 平台实现模式
  3. 03Ktor 网络请求
  4. 04SQLDelight 本地存储
  5. 05Compose Multiplatform 共享界面
  6. 06共享代码测试指导

适用场景

  1. 01规划共享业务逻辑与平台代码
  2. 02为多平台应用实现网络和本地存储
  3. 03测试 common 模块中的共享代码

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/travisjneuman/.claude --skill kotlin-multiplatform

安装后在 Claude Code 中输入/kotlin-multiplatform确认已加载。

详细介绍

Kotlin Multiplatform 技能

在 Android、iOS、桌面端和 Web 之间共享业务逻辑,并可选择共享 UI。


项目结构

project/
├── composeApp/                    # Shared Compose UI (if using CMP)
│   └── src/
│       ├── commonMain/            # Shared UI code
│       ├── androidMain/           # Android-specific UI
│       ├── iosMain/               # iOS-specific UI
│       └── desktopMain/          # Desktop-specific UI
├── shared/                        # Shared business logic (KMP)
│   └── src/
│       ├── commonMain/            # Shared code
│       │   └── kotlin/
│       │       ├── data/          # Repositories, data sources
│       │       ├── domain/        # Use cases, models
│       │       └── platform/      # expect declarations
│       ├── androidMain/           # actual implementations
│       ├── iosMain/               # actual implementations
│       └── commonTest/            # Shared tests
├── androidApp/                    # Android entry point
├── iosApp/                        # iOS entry point (Xcode project)
├── build.gradle.kts
└── settings.gradle.kts

expect/actual 模式

// commonMain - expect declaration
expect class PlatformContext

expect fun getPlatformName(): String

expect fun createHttpClient(): HttpClient

// androidMain - actual implementation
actual class PlatformContext(val context: android.content.Context)

actual fun getPlatformName(): String = "Android ${Build.VERSION.SDK_INT}"

actual fun createHttpClient(): HttpClient = HttpClient(OkHttp) {
    install(ContentNegotiation) { json() }
}

// iosMain - actual implementation
actual class PlatformContext

actual fun getPlatformName(): String = UIDevice.currentDevice.systemName()

actual fun createHttpClient(): HttpClient = HttpClient(Darwin) {
    install(ContentNegotiation) { json() }
}

主要库

库用途支持多平台?
KtorHTTP 客户端是
kotlinx.serializationJSON 解析是
kotlinx.coroutines异步/并发是
SQLDelight本地数据库是
Koin依赖注入是
Compose Multiplatform共享 UI是
kotlinx.datetime日期/时间是
Napier日志记录是

使用 Ktor 进行网络通信

// commonMain
class ApiClient(private val httpClient: HttpClient) {
    suspend fun getUsers(): List<User> {
        return httpClient.get("https://api.example.com/users").body()
    }

    suspend fun createUser(input: CreateUserInput): User {
        return httpClient.post("https://api.example.com/users") {
            contentType(ContentType.Application.Json)
            setBody(input)
        }.body()
    }
}

@Serializable
data class User(
    val id: String,
    val name: String,
    val email: String,
)

使用 SQLDelight 进行本地存储

-- src/commonMain/sqldelight/com/example/UserQueries.sq
CREATE TABLE user (
    id TEXT NOT NULL PRIMARY KEY,
    name TEXT NOT NULL,
    email TEXT NOT NULL,
    cached_at INTEGER NOT NULL
);

selectAll:
SELECT * FROM user ORDER BY name;

insertOrReplace:
INSERT OR REPLACE INTO user (id, name, email, cached_at)
VALUES (?, ?, ?, ?);

deleteById:
DELETE FROM user WHERE id = ?;

Compose Multiplatform UI

// commonMain - Shared composable
@Composable
fun UserListScreen(viewModel: UserListViewModel) {
    val users by viewModel.users.collectAsState()
    val isLoading by viewModel.isLoading.collectAsState()

    Scaffold(
        topBar = { TopAppBar(title = { Text("Users") }) }
    ) { padding ->
        if (isLoading) {
            CircularProgressIndicator(modifier = Modifier.padding(padding))
        } else {
            LazyColumn(modifier = Modifier.padding(padding)) {
                items(users) { user ->
                    UserRow(user = user, onClick = { viewModel.onUserClick(user.id) })
                }
            }
        }
    }
}

iOS 集成

Swift 互操作
// iosApp - Using shared Kotlin code from Swift
import shared

class UserViewController: UIViewController {
    private let viewModel = UserListViewModel()

    override func viewDidLoad() {
        super.viewDidLoad()
        viewModel.users.collect(collector: FlowCollector { users in
            // Update UI with users
        })
    }
}
CocoaPods 或 SPM 集成
// build.gradle.kts
kotlin {
    iosX64()
    iosArm64()
    iosSimulatorArm64()

    cocoapods {
        summary = "Shared module"
        homepage = "https://example.com"
        ios.deploymentTarget = "16.0"
        framework { baseName = "shared" }
    }
}

测试

// commonTest
class UserRepositoryTest {
    private val fakeApi = FakeApiClient()
    private val repository = UserRepository(fakeApi)

    @Test
    fun fetchUsersReturnsListFromApi() = runTest {
        fakeApi.setUsers(listOf(User("1", "Alice", "[email protected]")))

        val users = repository.getUsers()

        assertEquals(1, users.size)
        assertEquals("Alice", users.first().name)
    }
}

最佳实践

  • 共享业务逻辑(网络通信、存储、模型)——如有需要,保留原生平台 UI
  • 谨慎使用 expect/actual——优先使用接口,并通过 DI 提供平台实现
  • 保持共享模块精简——避免引入依赖平台特性过重的依赖项
  • 在 commonTest 中测试共享代码——它会在所有目标平台上运行
  • 对于不要求原生外观的新项目,使用 Compose Multiplatform

相关资源

  • ~/.claude/skills/android-development/SKILL.md - Android 模式
  • ~/.claude/skills/ios-development/SKILL.md - iOS 模式
  • agent-flutter-developer 技能 - 跨平台替代方案

共享逻辑,尊重平台。KMP 让你两全其美。

评论

支持 Markdown