如何使用 Room 在 kotlin android 开发中解析具有密封 class 参数的对象?
How to parse objects that has a sealed class param in kotlin android development using Room?
我有一个植物数据 class,它有一个 PlantType sealed class 参数。
我正在使用 Room 本地数据库,但是当我尝试解析它时失败了。它适用于具有可初始化 class 参数的其他 classes。
提前感谢您的帮助。
错误:
java.lang.RuntimeException: 调用没有参数的私有 com.tenyitamas.mylittlegarden.domain.util.PlantType() 失败
在 com.tenyitamas.mylittlegarden.data.util.Converters.fromPlantsJson(Converters.kt:99)
// 评论:Converters.kt:99 是转换器代码的 json 部分,我包括在内。
Plant.kt:
data class Plant(
val type: PlantType,
val upgrades: Upgrades
)
PlantType.kt:
sealed class PlantType {
object Carrot : PlantType()
object Tomato : PlantType()
object Cucumber : PlantType()
object Lettuce : PlantType()
object Strawberry : PlantType()
private companion object Constants {
const val INITIAL_TIME_CARROT = 5_000L // 5s
const val INITIAL_TIME_TOMATO = 6_000L
const val INITIAL_TIME_CUCUMBER = 7_000L
const val INITIAL_TIME_LETTUCE = 8_000L
const val INITIAL_TIME_STRAWBERRY = 9_000L
const val INITIAL_COST_CARROT = 10
const val INITIAL_COST_TOMATO = 100
const val INITIAL_COST_CUCUMBER = 1_000
const val INITIAL_COST_LETTUCE = 10_000
const val INITIAL_COST_STRAWBERRY = 100_000
const val INITIAL_INCOME_CARROT = 10
const val INITIAL_INCOME_TOMATO = 100
const val INITIAL_INCOME_CUCUMBER = 1_000
const val INITIAL_INCOME_LETTUCE = 10_000
const val INITIAL_INCOME_STRAWBERRY = 100_000
}
val name: String
get() {
return when (this) {
Carrot -> Resources.getSystem().getString(R.string.carrot)
Tomato -> Resources.getSystem().getString(R.string.tomato)
Cucumber -> Resources.getSystem().getString(R.string.cucumber)
Lettuce -> Resources.getSystem().getString(R.string.lettuce)
Strawberry -> Resources.getSystem().getString(R.string.strawberry)
}
}
val image: Bitmap
get() {
return when (this) {
Carrot -> {
BitmapFactory.decodeResource(Resources.getSystem(), R.drawable.ic_carrot)
}
Tomato -> {
BitmapFactory.decodeResource(Resources.getSystem(), R.drawable.ic_tomato)
}
Cucumber -> {
BitmapFactory.decodeResource(Resources.getSystem(), R.drawable.ic_cucumber)
}
Lettuce -> {
BitmapFactory.decodeResource(Resources.getSystem(), R.drawable.ic_lettuce)
}
Strawberry -> {
BitmapFactory.decodeResource(Resources.getSystem(), R.drawable.ic_strawberry)
}
}
}
val initialTime: Long
get() {
return when (this) {
Carrot -> INITIAL_TIME_CARROT
Tomato -> INITIAL_TIME_TOMATO
Cucumber -> INITIAL_TIME_CUCUMBER
Lettuce -> INITIAL_TIME_LETTUCE
Strawberry -> INITIAL_TIME_STRAWBERRY
}
}
val initialCost: Int
get() {
return when (this) {
Carrot -> INITIAL_COST_CARROT
Tomato -> INITIAL_COST_TOMATO
Cucumber -> INITIAL_COST_CUCUMBER
Lettuce -> INITIAL_COST_LETTUCE
Strawberry -> INITIAL_COST_STRAWBERRY
}
}
val initialIncome: Int
get() {
return when (this) {
Carrot -> INITIAL_INCOME_CARROT
Tomato -> INITIAL_INCOME_TOMATO
Cucumber -> INITIAL_INCOME_CUCUMBER
Lettuce -> INITIAL_INCOME_LETTUCE
Strawberry -> INITIAL_INCOME_STRAWBERRY
}
}
}
Converters.kt
@TypeConverter
fun fromPlantsJson(json: String): List<Plant> {
return jsonParser.fromJson<ArrayList<Plant>>(
json,
object : TypeToken<ArrayList<Plant>>(){}.type
) ?: emptyList()
}
@TypeConverter
fun toPlantsJson(plants: List<Plant>): String {
return jsonParser.toJson(
plants,
object : TypeToken<ArrayList<Plant>>(){}.type
) ?: "[]"
}
您的 PlantType
密封 class 里面只有物品。您可以为此使用一个枚举。
enum class PlantType {
Carrot, Tomato, Cucumber, Lettuce, Strawberry
}
而且您的 jsonParser
很可能能够序列化此枚举。
编辑: 在您编辑的问题中,您刚刚在 PlantType
class 中添加了一些新的 val
s,所有这些都有return 值取决于 PlantType
的自定义吸气剂。您仍然可以用枚举替换它,并将那些 val
作为扩展名放在 PlantType
.
上
例如,
enum class PlantType {
Carrot, Tomato, Cucumber, Lettuce, Strawberry
}
val PlantType.name: String
get() {
return when (this) {
Carrot -> Resources.getSystem().getString(R.string.carrot)
Tomato -> Resources.getSystem().getString(R.string.tomato)
Cucumber -> Resources.getSystem().getString(R.string.cucumber)
Lettuce -> Resources.getSystem().getString(R.string.lettuce)
Strawberry -> Resources.getSystem().getString(R.string.strawberry)
}
}
我有一个植物数据 class,它有一个 PlantType sealed class 参数。 我正在使用 Room 本地数据库,但是当我尝试解析它时失败了。它适用于具有可初始化 class 参数的其他 classes。
提前感谢您的帮助。
错误:
java.lang.RuntimeException: 调用没有参数的私有 com.tenyitamas.mylittlegarden.domain.util.PlantType() 失败
在 com.tenyitamas.mylittlegarden.data.util.Converters.fromPlantsJson(Converters.kt:99)
// 评论:Converters.kt:99 是转换器代码的 json 部分,我包括在内。
Plant.kt:
data class Plant(
val type: PlantType,
val upgrades: Upgrades
)
PlantType.kt:
sealed class PlantType {
object Carrot : PlantType()
object Tomato : PlantType()
object Cucumber : PlantType()
object Lettuce : PlantType()
object Strawberry : PlantType()
private companion object Constants {
const val INITIAL_TIME_CARROT = 5_000L // 5s
const val INITIAL_TIME_TOMATO = 6_000L
const val INITIAL_TIME_CUCUMBER = 7_000L
const val INITIAL_TIME_LETTUCE = 8_000L
const val INITIAL_TIME_STRAWBERRY = 9_000L
const val INITIAL_COST_CARROT = 10
const val INITIAL_COST_TOMATO = 100
const val INITIAL_COST_CUCUMBER = 1_000
const val INITIAL_COST_LETTUCE = 10_000
const val INITIAL_COST_STRAWBERRY = 100_000
const val INITIAL_INCOME_CARROT = 10
const val INITIAL_INCOME_TOMATO = 100
const val INITIAL_INCOME_CUCUMBER = 1_000
const val INITIAL_INCOME_LETTUCE = 10_000
const val INITIAL_INCOME_STRAWBERRY = 100_000
}
val name: String
get() {
return when (this) {
Carrot -> Resources.getSystem().getString(R.string.carrot)
Tomato -> Resources.getSystem().getString(R.string.tomato)
Cucumber -> Resources.getSystem().getString(R.string.cucumber)
Lettuce -> Resources.getSystem().getString(R.string.lettuce)
Strawberry -> Resources.getSystem().getString(R.string.strawberry)
}
}
val image: Bitmap
get() {
return when (this) {
Carrot -> {
BitmapFactory.decodeResource(Resources.getSystem(), R.drawable.ic_carrot)
}
Tomato -> {
BitmapFactory.decodeResource(Resources.getSystem(), R.drawable.ic_tomato)
}
Cucumber -> {
BitmapFactory.decodeResource(Resources.getSystem(), R.drawable.ic_cucumber)
}
Lettuce -> {
BitmapFactory.decodeResource(Resources.getSystem(), R.drawable.ic_lettuce)
}
Strawberry -> {
BitmapFactory.decodeResource(Resources.getSystem(), R.drawable.ic_strawberry)
}
}
}
val initialTime: Long
get() {
return when (this) {
Carrot -> INITIAL_TIME_CARROT
Tomato -> INITIAL_TIME_TOMATO
Cucumber -> INITIAL_TIME_CUCUMBER
Lettuce -> INITIAL_TIME_LETTUCE
Strawberry -> INITIAL_TIME_STRAWBERRY
}
}
val initialCost: Int
get() {
return when (this) {
Carrot -> INITIAL_COST_CARROT
Tomato -> INITIAL_COST_TOMATO
Cucumber -> INITIAL_COST_CUCUMBER
Lettuce -> INITIAL_COST_LETTUCE
Strawberry -> INITIAL_COST_STRAWBERRY
}
}
val initialIncome: Int
get() {
return when (this) {
Carrot -> INITIAL_INCOME_CARROT
Tomato -> INITIAL_INCOME_TOMATO
Cucumber -> INITIAL_INCOME_CUCUMBER
Lettuce -> INITIAL_INCOME_LETTUCE
Strawberry -> INITIAL_INCOME_STRAWBERRY
}
}
}
Converters.kt
@TypeConverter
fun fromPlantsJson(json: String): List<Plant> {
return jsonParser.fromJson<ArrayList<Plant>>(
json,
object : TypeToken<ArrayList<Plant>>(){}.type
) ?: emptyList()
}
@TypeConverter
fun toPlantsJson(plants: List<Plant>): String {
return jsonParser.toJson(
plants,
object : TypeToken<ArrayList<Plant>>(){}.type
) ?: "[]"
}
您的 PlantType
密封 class 里面只有物品。您可以为此使用一个枚举。
enum class PlantType {
Carrot, Tomato, Cucumber, Lettuce, Strawberry
}
而且您的 jsonParser
很可能能够序列化此枚举。
编辑: 在您编辑的问题中,您刚刚在 PlantType
class 中添加了一些新的 val
s,所有这些都有return 值取决于 PlantType
的自定义吸气剂。您仍然可以用枚举替换它,并将那些 val
作为扩展名放在 PlantType
.
例如,
enum class PlantType {
Carrot, Tomato, Cucumber, Lettuce, Strawberry
}
val PlantType.name: String
get() {
return when (this) {
Carrot -> Resources.getSystem().getString(R.string.carrot)
Tomato -> Resources.getSystem().getString(R.string.tomato)
Cucumber -> Resources.getSystem().getString(R.string.cucumber)
Lettuce -> Resources.getSystem().getString(R.string.lettuce)
Strawberry -> Resources.getSystem().getString(R.string.strawberry)
}
}