我试图使用一个具有值类的房间实体:
@JvmInline
value class UserToken(val token: String)
和实体:
@Entity(tableName = TABLE_AUTH_TOKEN)
data class TokenEntity(
@PrimaryKey val id: Int = 0,
val token: UserToken
)
我得到以下错误:
error: Entities and POJOs must have a usable public constructor. You can have an empty constructor or a constructor whose parameters match the fields (by name and type).
public final class TokenEntity {
^
甚至可以使用房间与值类吗?我找不到任何关于这个的资料。由于
请看@CommonsWare的评论。Android还不支持Room的值类。
对于kotlin 1.5中引入的值类也是如此。不支持该类型
-在Room实体中支持内联类
这是一个可能的解释,根据Kotlin Inline Classes in an Android World
想要解决这个问题,你可以尝试为你的内联类添加一个
TypeConverter
,但是因为你的内联类只是它在编译时包装的值,这没有多大意义,它不像你期望的那样工作,即使你尝试过…我只是猜测这是因为这是一个
TypeConverter
转换UserId
到Int
,这基本上是相同的Int
到Int
😭。有人可能会解决这个问题,但如果你必须为你的内联类创建一个TypeConverter
,那么你仍然要加一个类计数(multidex)。👎
根据谷歌问题跟踪器,值类现在支持房间版本2.6.0-alpha01
。要能够构建,请遵循以下步骤:
为Room编译器使用KSP而不是KAPT。将插件添加到根构建中。或者您可以参考从KAPT迁移到KSP指南
添加到项目build.gradle
plugins {
...
id 'com.google.devtools.ksp' version '1.8.10-1.0.9' apply false
}
在应用程序build.gradle
plugins {
....
id 'com.google.devtools.ksp'
}
android {
...
ksp {
arg("room.generateKotlin", "true")
}
}
dependencies {
...
implementation "androidx.room:room-ktx:2.6.0-alpha01"
ksp "androidx.room:room-compiler:2.6.0-alpha01"
}
如果value类有一个公共构造函数,就不需要再为它编写TypeConverter
了。但是,如果它具有private constructor
,或者它是具有internal constructor
的第三方类,则需要提供TypeConverter
来构建它。例如:kotlin.time.Duration
.
class Converters {
@TypeConverter
fun formDuration(value: Duration?): Long? {
return value?.inWholeMilliseconds
}
@TypeConverter
fun toDuration(time: Long?): Duration? {
return time?.let { time.milliseconds }
}
}
@Database(
...
)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
...
}
我想是的,如果你可以提供一个类型转换器改变它某种原始数据类型(int,长字符串,…等)需要存储,并改变它回到它的类类型时从数据库获取。
你可以从这里阅读关于类型转换器
使用Room
引用复杂数据除此之外,你的其他类应该是一个实体,并使用关系将你的两个实体绑定在一起。
至少我知道如何使用Room。
UserToken总是只有一个属性?在这种情况下,您不需要两个类,只需使用令牌:直接在实体类上;
如果你真的需要保持这门课,你有两个选择:
-
TypeConverter,你基本上将对象转换成json,并保存为字符串在数据库中;
-
关系,您将在其中转换实体中的UserToken,并在TokenEntity上保存tokenId。