android Room withKotlinvalue class?

oknrviil  于 2023-04-10  发布在  Android
关注(0)|答案(4)|浏览(118)

我正在尝试使用一个房间实体和一个值类:

@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 {
             ^

有没有可能使用超值房间?我找不到任何关于这个的信息。谢谢

holgip5t

holgip5t1#

请参阅@CommonsWare的评论。Android尚未支持Room的值类。
Kotlin1.5中引入的值类也是如此。不支持该类型。

  • Support Inline class in Room entity
    下面是根据Kotlin Inline Classes in an Android World的可能解释。
    想要解决这个问题,你可以尝试为你的Inline类添加一个TypeConverter,但是由于你的Inline类只是它在编译时 Package 的值,这没有多大意义,即使你尝试了,它也不会像你期望的那样工作。
    我只是猜测这是因为这是一个TypeConverter转换UserIdInt,这基本上是相同的IntInt😭。有人可能会解决这个问题,但如果你必须为你的内联类创建一个TypeConverter,那么你仍然是多一个类的计数(multidex)。👎
icnyk63a

icnyk63a2#

根据Google Issue Tracker,Room版本2.6.0-alpha01现在支持值类。要能够构建,请按照以下步骤操作:
使用KSP而不是KAPT作为Room编译器。将插件添加到root build.gradle,或者您可以参考Migrate from KAPT to KSP指南
添加到项目build.gradle

plugins {
    ...
    id 'com.google.devtools.ksp' version '1.8.10-1.0.9' apply false
}

appbuild.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"
}

可选:如果值类有一个公共构造函数,你就不需要再为它写一个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() {
    ...
}
f3temu5u

f3temu5u3#

我认为是的,如果你可以提供一个类型转换器,当它需要存储时,将它更改为某种原始数据类型(int,string,long ...等),并在从数据库中获取时将其更改回其类类型。
您可以从这里阅读有关类型转换器的信息
使用Room引用复杂数据
除此之外,你的另一个类应该是一个实体,并使用Relation将你的实体绑定在一起。
至少这是我知道如何使用房间。

7vux5j2d

7vux5j2d4#

UserToken总是只有一个属性吗?这种情况下,你不需要两个类,只需要使用token:String直接在你的实体类上;
如果你真的需要保留这个类,你有两个选择:

  • TypeConverter,你基本上会将对象转换为JSON,并在数据库中保存为字符串;
  • 关系,在这里您将转换实体中的UserToken,并在TokenEntity保存tokenId。

相关问题