Kotlin Multiplatform Room中如何使用实验类型kotlin.time.Instant?
解决Kotlin Multiplatform Room中使用kotlin.time.Instant的实验API报错问题
问题背景
使用Kotlin Multiplatform Room 2.7.1 + KSP 2.1.21-2.0.1时,在实体模型中使用kotlin.time.Instant这个实验性类型,会触发编译器报错:
This declaration needs opt-in. Its usage must be marked with '@kotlin.time.ExperimentalTime' or '@OptIn(kotlin.time.ExperimentalTime::class)'
即使在实体类、构造函数、成员变量、DAO接口、类型转换器上都添加了@OptIn(ExperimentalTime::class)注解,错误依然存在——原因是KSP自动生成的DAO实现代码里,访问Instant字段和调用转换器方法时没有携带OptIn注解,编译器依然会拦截这些调用。
解决方案
直接通过全局编译器参数开启对kotlin.time.ExperimentalTime实验API的全局许可,让编译器默认允许整个项目使用该API,无需在每个用到的地方单独加注解。
1. 修改Gradle配置
根据项目类型(多平台/单平台),在模块的build.gradle.kts中添加以下配置:
Kotlin Multiplatform项目
kotlin { targets.all { compilations.all { kotlinOptions { freeCompilerArgs += "-opt-in=kotlin.time.ExperimentalTime" } } } }
单平台(如JVM)项目
kotlin { jvm { compilations.all { kotlinOptions { freeCompilerArgs += "-opt-in=kotlin.time.ExperimentalTime" } } } }
2. 简化代码(可选)
全局开启后,之前手动添加的@OptIn(ExperimentalTime::class)注解可以全部移除,代码会更简洁:
@Database( version = 1, entities = [RoomEntityModel::class], ) @TypeConverters(RoomDataConverters::class) abstract class AppDatabase : RoomDatabase() { abstract fun getRoomEntityDao(): RoomEntityModelDao } class RoomDataConverters { @TypeConverter fun nullableInstantToString(value: Instant?) = value?.toString() @TypeConverter fun instantToString(value: Instant) = value.toString() @TypeConverter fun nullableStringToInstant(value: String?) = value?.let { Instant.parse(it) } @TypeConverter fun stringToInstant(value: String) = Instant.parse(value) } @Dao interface RoomEntityModelDao { @Insert suspend fun insert(vararg models: RoomEntityModel) } @Entity("RoomEntityModel") data class RoomEntityModel( @PrimaryKey @ColumnInfo("instant") val instant: Instant, )
原理说明
KSP生成的DAO实现代码属于编译期自动生成的代码,无法手动修改其注解。全局编译器参数-opt-in=kotlin.time.ExperimentalTime会告知Kotlin编译器:整个项目范围内允许使用该实验性API,无需检查每个调用点的OptIn注解,从根源上解决生成代码的报错问题。
内容的提问来源于stack exchange,提问作者Gamer2015
相关产品推荐
相关产品推荐

