android - 如何在实现 GSON 的数据类中创建计算属性?
问题描述
背景:GSON、Kotlin、改造
我正在写一个餐厅应用程序。在主页中,用户可以加载餐厅品牌列表。每个品牌最多可以有 3 种美食类型,第一种是非空的,接下来的两种是可空的。每种美食类型都在 CuisineType 枚举类中。
我想做的是创建一个像这样的连接字符串:美食类型 1.标题 + 美食类型 2?.标题 + 美食类型 3?.标题 = 组合美食。这可以使一个 textView 中的所有美食都以中文显示。为了做到这一点,我创建了一个助手类。在这个助手类中,如果 Brand 中的 CuisineType 无法映射任何枚举成员,它将显示 Brand JSON 中的原始名称(以防服务器错误)。我尝试了下面注释掉的三种解决方案,但它们都不起作用。很多帮助将不胜感激。提前致谢!
data class Brand(
@SerializedName("id")
val id: Int,
@SerializedName("name_en")
val nameEN: String?,
@SerializedName("cuisine_1")
val cuisineType1: String,
@SerializedName("cuisine_2")
val cuisineType2: String?,
@SerializedName("cuisine_3")
val cuisineType3: String?,
/*Solution 1(not working):
val combinedCuisines = CombineCuisineHelper.combineCuisines(cuisineType1, cuisineType2, cuisineType3)
***java.lang.IllegalArgumentException: Unable to create converter for class
*/
/*Solution 2(not working):
@Transient
val combinedCuisines = CombineCuisineHelper.combineCuisines(cuisineType1, cuisineType2, cuisineType3)
***combinedCuisines = null after network call in fragment
*/
) {
/* Solution 3(not working):
val combinedCuisines: String
get() = CombineCuisineHelper.combineCuisines(cuisineType1, cuisineType2, cuisineType3)
***problem with GSON, I can only map the @SerializedName from the Cuisine enum class and will only run the illegal argument solution from the CombineCuisineHelper. For example, get hong_kong_style from the JSON brand but it will not convert to HongKongStyle and map to its title.
*/
}
//It should be a long list but I shortened it.
enum class CuisineType {
@SerializedName("chinese")
Chinese,
@SerializedName("hong_kong_style")
HongKongStyle,
@SerializedName("cantonese")
Cantonese,
val title: Double
get() {
return when (this) {
Chinese -> "中菜"
HongKongStyle -> "港式"
Cantonese -> "粵式"
}
class CombineCuisineHelper {
companion object {
fun combineCuisines(cuisineSubtype1: String, cuisineSubtype2: String?, cuisineSubtype3: String?): String {
val combinedSubtypes = ArrayList<String?>()
combinedSubtypes += try {
CuisineSubtype.valueOf(cuisineSubtype1).title
} catch (e: IllegalArgumentException) {
cuisineSubtype1
}
if (cuisineSubtype2 != null) {
combinedSubtypes += try {
CuisineSubtype.valueOf(cuisineSubtype2).title
} catch (e: IllegalArgumentException) {
cuisineSubtype2
}
}
if (cuisineSubtype3 != null) {
combinedSubtypes += try {
CuisineSubtype.valueOf(cuisineSubtype3).title
} catch (e: IllegalArgumentException) {
cuisineSubtype3
}
}
}
解决方案
第一种和第二种解决方案都不好,因为数据可能在初始化时还没有准备好。第三种解决方案是我们可以继续进行的解决方案:
val combinedCuisines: String
get() = CombineCuisineHelper.combineCuisines(cuisineType1, cuisineType2, cuisineType3)
s对于SerializedName
枚举常量没有用,也不会像您期望的那样为您工作。所以valueOf
枚举的方法不会找到像这样的文字的值,"hong_kong_style"
并且会抛出异常。
您可以像这样在枚举类中创建自己的辅助方法:
enum class CuisineType {
Chinese,
HongKongStyle,
Cantonese;
val title: String
get() {
return when (this) {
Chinese -> "中菜"
HongKongStyle -> "港式"
Cantonese -> "粵式"
}
}
companion object {
//Note this helper method which manually maps string values to enum constants:
fun enumValue(title: String): CuisineType = when (title) {
"chinese" -> Chinese
"hong_kong_style" -> HongKongStyle
"cantonese" -> Cantonese
else -> throw IllegalArgumentException("Unknown cuisine type $title")
}
}
}
然后使用这个新方法而不是枚举自己的valueOf
方法:
val combinedSubtypes = ArrayList<String?>()
combinedSubtypes += try {
CuisineType.enumValue(cuisineSubtype1).title
} catch (e: IllegalArgumentException) {
cuisineSubtype1
}
//continued...
推荐阅读
- typescript - Ramda typescript 给出 typescript 编译错误
- r - R Plotly - 为 x 轴变量使用别名
- jquery - 如何使用 ol 地图在多个坐标上添加标记?
- linux - Fasta 文件 - 行问题
- python - 是否可以声明静态类型变量?
- ios - 从 XCTest UI 测试中的活动呼叫中打开 CallKit 屏幕
- django - 在 AWS 上自动部署我的应用程序的最佳方式是什么?
- firebase - Firebase - 如何在 where 子句中检查子集合是否不为空或为空?
- node.js - 使用命名空间的类的参数化构造函数时的编译器错误
- sql - 更新员工每工作一整年的工资