最佳实践清单
基于多个成功的 KMP 项目经验,总结出以下最佳实践,帮助开发者避开常见陷阱,构建高质量的跨平台应用。
架构设计
✅ 分层架构
UI Layer (平台特定)
↓
Presentation Layer (共享 ViewModel 逻辑)
↓
Domain Layer (共享业务逻辑)
↓
Data Layer (共享数据访问)
↓
Platform Layer (平台 API 抽象)实施要点:
- UI 层使用平台原生技术(SwiftUI, Compose)
- ViewModel 核心逻辑共享,平台特定部分用 expect/actual
- 业务逻辑 100% 共享在 commonMain
- 数据层定义接口,平台层实现
✅ 依赖注入
kotlin
// 使用 Koin 统一管理依赖
val sharedModules = listOf(
dataModule, // 数据层
domainModule, // 业务层
networkModule // 网络层
)
// 平台特定模块
val platformModules = when (platform) {
Platform.Android -> androidModules
Platform.iOS -> iosModules
}
startKoin {
modules(sharedModules + platformModules)
}代码组织
✅ 最大化代码共享
共享率目标:
- 业务逻辑:90-100%
- 数据层:80-90%
- UI 逻辑:50-70%
- UI 渲染:0-50%(取决于是否使用 Compose Multiplatform)
策略:
- 优先在 commonMain 实现
- 仅在必要时使用 expect/actual
- 使用接口 + DI 处理平台差异
- UI 复杂时考虑 Compose Multiplatform
✅ 模块化
shared/
├── core/ # 核心工具
├── data/ # 数据层
├── domain/ # 业务层
├── feature-auth/ # 认证功能
├── feature-user/ # 用户功能
└── feature-post/ # 帖子功能性能优化
✅ 编译时间优化
kotlin
// 1. 使用 Configuration Cache
org.gradle.configuration-cache=true
// 2. 增加堆内存
org.gradle.jvmargs=-Xmx4g
// 3. 并行构建
org.gradle.parallel=true
// 4. 使用 Build Cache
org.gradle.caching=true✅ 运行时性能
kotlin
// 避免频繁创建对象
class UserRepository {
private val cache = LruCache<String, User>(100)
suspend fun getUser(id: String): User {
return cache.get(id) ?: fetchAndCache(id)
}
}
// 使用协程而非回调
suspend fun loadData(): List<Data> { } // ✅
fun loadData(callback: (List<Data>) -> Unit) { } // ❌✅ iOS Framework 体积优化
kotlin
// build.gradle.kts
kotlin {
iosTarget.binaries.framework {
// 启用 bitcode(可选)
embedBitcode = EmbedBitcodeMode.BITCODE
// 优化编译
freeCompilerArgs += listOf(
"-Xoverride-konan-properties=minification.enabled=true"
)
}
}错误处理
✅ 统一错误处理
kotlin
sealed class Result<out T> {
data class Success<T>(val data: T) : Result<T>()
data class Error(val exception: Exception) : Result<Nothing>()
data object Loading : Result<Nothing>()
}
// 使用
suspend fun getUser(id: String): Result<User> {
return try {
Result.Success(api.fetchUser(id))
} catch (e: Exception) {
Result.Error(e)
}
}✅ 平台特定错误映射
kotlin
// commonMain
sealed class AppException : Exception() {
data class Network(override val message: String) : AppException()
data class NotFound(val id: String) : AppException()
}
// 平台层转换
expect fun Throwable.toAppException(): AppException
// androidMain
actual fun Throwable.toAppException(): AppException {
return when (this) {
is IOException -> AppException.Network(message ?: "Network error")
is HttpException -> when (code()) {
404 -> AppException.NotFound(message())
else -> AppException.Network(message())
}
else -> AppException.Network("Unknown error")
}
}测试策略
✅ 测试金字塔
UI Tests (5%)
↑
Integration Tests (15%)
↑
Unit Tests (80%)实施:
- 80% 单元测试(commonTest)
- 15% 集成测试(platform-specific)
- 5% UI 测试(platform-specific)
✅ 共享测试代码
kotlin
// commonTest
abstract class RepositoryTest {
abstract fun createRepository(): UserRepository
@Test
fun testGetUser() = runTest {
val repository = createRepository()
val user = repository.getUser("123")
assertEquals("Alice", user.name)
}
}
// androidTest
class AndroidRepositoryTest : RepositoryTest() {
override fun createRepository() = AndroidUserRepository()
}
// iosTest
class IosRepositoryTest : RepositoryTest() {
override fun createRepository() = IosUserRepository()
}版本管理
✅ 统一版本号
toml
# gradle/libs.versions.toml
[versions]
app-version = "1.2.0"
app-version-code = "10200"
# 在各平台使用
# Android: versionName, versionCode
# iOS: CFBundleShortVersionString, CFBundleVersion✅ 依赖版本锁定
kotlin
// 锁定核心依赖版本
kotlin = "2.3.0" # 精确版本
ktor = "3.0.+" # 允许修订版更新
compose = "1.7.6" # 锁定次版本CI/CD
✅ 自动化流程
yaml
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Run tests
run: ./gradlew allTests
- name: Build iOS framework
run: ./gradlew linkDebugFrameworkIosArm64
- name: Build Android AAR
run: ./gradlew assembleRelease文档与协作
✅ 文档规范
- README.md - 项目概览、环境配置
- docs/architecture.md - 架构设计
- docs/api.md - API 文档
- CHANGELOG.md - 版本变更记录
✅ 代码规范
kotlin
// KDoc 注释
/**
* 获取指定用户信息
*
* @param id 用户 ID
* @return 用户对象,如果不存在则返回 null
* @throws NetworkException 网络错误
*/
suspend fun getUser(id: String): User?常见陷阱避开
❌ 避免在 commonMain 依赖平台库
kotlin
// ❌ 错误
// commonMain
import android.util.Log // 编译错误
// ✅ 正确
// commonMain
expect fun log(message: String)
// androidMain
actual fun log(message: String) {
android.util.Log.d("App", message)
}❌ 避免过度使用 expect/actual
kotlin
// ❌ 不必要的 expect/actual
expect fun add(a: Int, b: Int): Int
// ✅ 直接在 commonMain 实现
fun add(a: Int, b: Int): Int = a + b❌ 避免平台代码泄漏
kotlin
// ❌ 暴露平台类型
fun getUserContext(): android.content.Context
// ✅ 使用抽象
expect class PlatformContext
fun getUserContext(): PlatformContext清单总结
架构:
- ✅ 使用分层架构
- ✅ 依赖注入管理依赖
- ✅ 最大化代码共享
代码质量:
- ✅ 80%+ 单元测试覆盖
- ✅ 统一错误处理
- ✅ 代码审查流程
性能:
- ✅ 优化编译时间
- ✅ 减少 iOS Framework 体积
- ✅ 使用缓存策略
工程化:
- ✅ CI/CD 自动化
- ✅ 版本统一管理
- ✅ 完善文档
遵循这些最佳实践,可以构建高质量、可维护的 Kotlin Multiplatform 应用。