Kotlin data class 重写getter setter处理,支持Parcelable的intent传递和Gson解析

时间:2021-01-29 20:08:20

一、 前言

Kotlin的data class是不支持直接get和set的,于是有些需要修改实体参数的需求就做不了。

在百度或谷歌搜索到的其他文章,有说是定义一个新的属性在内部,但是这样子并不适合我们在项目中使用。

二、 例子

价格的处理:服务器要求价格的单位是分,但是移动端显示和填写的时候需要单位为元,这个时候需要我们在实体类的进行分和元的转换处理。

一个商品实体类

data class Goods(
    var name: String,
    var price: Int    //价格,服务器要求单位是分
)

我们显示的时候需要变成元,这时候需要改造实体类,在内部重新定义属性,重写get方法:

data class Goods(
    var name: String,
    var _price: Int    //价格,服务器要求单位是分
){
    //在内部重新定义属性,重写get方法
    var price: Float = 0F
        get(){
            return field / 100
        }
}

这个时候往你项目里面一放,问题就出来了: 从服务器获取数据之后,价格一直是0

因为解析的时候,price属性在内部Gson是解析赋值不了的,所以,我们需要指定解析属性,添加注解@SerializedName, 这样子的话,gson解析出来的实体类就有数据了

data class Goods(
    var name: String,
    var _price: Int    //价格,服务器要求单位是分
){
    //添加注解,让gson解析赋值
    @SerializedName("price")
    var price: Float = 0F
        get(){
            return field / 100
        }
}

然后,问题又来了: 实体类需要activity之间传递,需要用到Parcelable,这里要注意,在write的时候,需要乘以100 ,为什么呢? 因为get的时候已经除以100了。 这个时候 传递到下个activity的价格_price就是服务器的价格,但是注意了,price会是0,为什么呢, 因为没传递,所以需要赋值_price的价格到price

data class Goods(
    var name: String,
    var _price: Int    //价格,服务器要求单位是分
){
    //添加注解,让gson解析赋值
    @SerializedName("price")
    var price: Float = 0F
        get(){
            var realValue = field
            if (realValue == 0F) {
                realValue = _price   //实体类传递到了其他Activity,赋值回来
            }
            return realValue / 100
        }


    override fun writeToParcel(dest: Parcel, flags: Int) = with(dest) {
        writeString(name)
        writeInt(price * 100)   //注意这里需要恢复服务器的数据
    }
    ...
}