代码之家  ›  专栏  ›  技术社区  ›  Jack Guo

Android房间类型转换多个枚举类型

  •  6
  • Jack Guo  · 技术社区  · 6 年前

    我正在为我的房间数据库编写类型转换器。我有几个自定义枚举类,当存储在数据库中时,我想将它们全部转换为序号。因此,没有为每个类编写以下内容,有没有任何方法可以简化它(例如传入通用枚举类型)?

    class Converter {
    
        @TypeConverter
        fun toOrdinal(type: TypeA): Int = type.ordinal
    
        @TypeConverter
        fun toTypeA(ordinal: Int): TypeA = TypeA.values().first { it.ordinal == ordinal }
    
        @TypeConverter
        fun toOrdinal(type: TypeB): Int = type.ordinal
    
        @TypeConverter
        fun toTypeB(ordinal: Int): TypeB = TypeB.values().first { it.ordinal == ordinal }
    
        ...
    }
    
    2 回复  |  直到 6 年前
        1
  •  10
  •   zsmb13    6 年前

    here

    @Suppress("NOTHING_TO_INLINE")
    private inline fun <T : Enum<T>> T.toInt(): Int = this.ordinal
    
    private inline fun <reified T : Enum<T>> Int.toEnum(): T = enumValues<T>()[this]
    

    @TypeConverter fun myEnumToTnt(value: MyEnum) = value.toInt()
    @TypeConverter fun intToMyEnum(value: Int) = value.toEnum<MyEnum>()
    

    @TypeConverter fun myEnumToTnt(value: MyEnum?) = value?.toInt()
    @TypeConverter fun intToMyEnum(value: Int?) = value?.toEnum<MyEnum>()
    
        2
  •  1
  •   HawkPriest    6 年前

    interface BaseType {
        val arg0: String
    
        fun asString() : String? {
            return when(this) {
                is TypeA -> "${TypeA::class.simpleName}$separatorParam$arg0"
                is TypeB -> "${TypeB::class.simpleName}$separatorParam$arg0"
                else -> null
            }
        }
    
        companion object {
            const val separatorParam = "::"
        }
    }
    
    enum class TypeA (override val arg0: String) : BaseType {
        A_ONE("argument 1"),
        A_TWO("argument 2");
    
        companion object {
            fun getValueTypes(arg0: String) : TypeA? = values().firstOrNull { it.arg0 == arg0 }
        }
    }
    
    enum class TypeB (override val arg0: String) : BaseType {
        A_ONE("argument 1"),
        A_TWO("argument 2");
    
        companion object {
            fun getValueTypes(arg0: String) : TypeB? = values().firstOrNull { it.arg0 == arg0 }
        }
    }
    
    class Converter {
        @TypeConverter
        fun fromBaseType(type: BaseType) : String? = type.asString()
    
        @TypeConverter
        fun toBaseType(param: String?) : BaseType? = param?.asBaseType()
    
        private fun String.asBaseType() : BaseType? {
            val stringArray = this.split(BaseType.separatorParam)
            val className : String? = stringArray[0]
            return when(className) {
                TypeA::class.simpleName -> TypeA.getValueTypes(stringArray[1])
                TypeB::class.simpleName -> TypeB.getValueTypes(stringArray[1])
                else -> null
            }
        }
    }
    

    data class

    data class MyDbModel(val baseType: BaseType) {
        inline fun <reified T: BaseType> getTypeAs() : T? = 
                when(baseType) {
                    is TypeA -> TypeA.getValueTypes(baseType.arg0) as? T
                    is TypeB -> TypeB.getValueTypes(baseType.arg0) as? T
                    else -> null
                }
    }
    
    fun foo() {
        val model = MyDbModel(TypeA.A_ONE)
        val type = model.getTypeAs<TypeA>()
    }
    

    这种方法的缺点是它只适用于 arg0 R.id.a_one 作为第一个参数,第二个参数可以是字符串。