升级Kotlin 1.9.0与Compose Compiler后KMM项目注解不匹配报错
解决方案:修复KMM中expect/actual的@Composable注解不匹配问题
环境信息
- AGP版本:
8.1.0-rc01 - Compose Compiler版本:
1.5.0-dev-k1.9.0-6a60475e07f - Kotlin版本:
1.9.0 - KSP版本:
1.9.0-1.0.11
问题原因
Kotlin 1.9.0搭配Compose Compiler 1.5.0-dev版本后,对expect/actual声明的签名一致性(包括注解)检查大幅收紧。此前Kotlin 1.8.21+Compose 1.4.8允许Android端的actual声明单独添加@Composable注解,但新版本会触发Mismatched @Composable annotation between expect and actual declaration错误。
修复步骤
1. 在commonMain中定义平台化注解
创建预期的注解,统一跨平台的注解声明:
// commonMain expect annotation class PlatformComposable() expect annotation class PlatformUiComposable()
2. 在androidMain中映射为Compose原生注解
将自定义注解映射为Android端需要的Compose注解:
// androidMain import androidx.compose.runtime.Composable import androidx.compose.ui.UiComposable actual typealias PlatformComposable = Composable actual typealias PlatformUiComposable = UiComposable
3. 在iosMain中定义空注解
iOS端不需要Compose注解,直接定义空注解占位:
// iosMain actual annotation class PlatformComposable() actual annotation class PlatformUiComposable()
4. 修改commonMain的expect声明
为expect中的参数和方法添加平台化注解,保证与actual签名一致:
// commonMain interface IssueFixClass { } expect class IssueFixNoneClass private constructor(content: @PlatformComposable @PlatformUiComposable () -> Unit) : IssueFixClass { @PlatformComposable @PlatformUiComposable fun invoke() companion object Delegate { fun makeClass(content: @PlatformComposable @PlatformUiComposable () -> Unit): IssueFixNoneClass } }
5. 调整Android端的actual实现
直接使用平台化注解(与原生Compose注解等价):
// androidMain import android.annotation.SuppressLint actual class IssueFixNoneClass private actual constructor(private val content: @PlatformComposable @PlatformUiComposable () -> Unit) : IssueFixClass { @SuppressLint("ComposableNaming") @PlatformComposable @PlatformUiComposable actual fun invoke() { content.invoke() } actual companion object Delegate { actual fun makeClass(content: @PlatformComposable @PlatformUiComposable () -> Unit): IssueFixNoneClass { return IssueFixNoneClass(content) } } }
6. 调整iOS端的actual实现
添加平台化注解占位,保证与expect签名一致:
// iosMain actual class IssueFixNoneClass private actual constructor(private val content: @PlatformComposable @PlatformUiComposable () -> Unit) : IssueFixClass { @PlatformComposable @PlatformUiComposable actual fun invoke() { content.invoke() } actual companion object Delegate { actual fun makeClass(content: @PlatformComposable @PlatformUiComposable () -> Unit): IssueFixNoneClass { return IssueFixNoneClass(content) } } }
效果
修改后,expect与actual的签名(包括注解)完全匹配,Android端的Compose注解正常生效,iOS端的空注解不影响运行,项目可正常编译。
内容的提问来源于stack exchange,提问作者vicky leu
相关产品推荐
相关产品推荐

