kotlin 实现了Parcelable但是Activity之间传递时ArrayList的值为什么还是为null?

大家都知道想要在Activity之间传递对象数据时可以通过实现Parcelable,在java代码中,我们一般用Android Studio插件(Android Parcelable code generator)来生成Parcelable需要的代码,但是在kotlin代码中不需要使用第三方插件,Android Studio自带编辑器就可以自动生成kotlin代码的Parcelable实现,之前的插件也在kotlin里无法使用,在windows上,我们定位到类名,按ALT+Enter组合键就可以出现一个菜单如下:
在这里插入图片描述
选择第一个就会自动帮我们生成Parcelable需要的代码如下图所示:

class DemoBean() :Parcelable{
    var name: String? = null
    var images: ArrayList<String>? = null

    constructor(parcel: Parcel) : this() {
        name = parcel.readString()
    }

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(name)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<DemoBean> {
        override fun createFromParcel(parcel: Parcel): DemoBean {
            return DemoBean(parcel)
        }

        override fun newArray(size: Int): Array<DemoBean?> {
            return arrayOfNulls(size)
        }
    }
}

回到上面标题遇到的问题:

kotlin 实现了Parcelable但是Activity之间传递时ArrayList的值为什么还是为null?

从上面生成的Parcelable代码可以看到,它并没有为我们的images这个变量生成Parcelable代码实现,这就是为什么在跳转Activity后这个对象的ArrayList对应的变量值都为null的原因。

那么Android Studio为什么不帮我们生成ArrayList的Parcelable代码呢?是不是在kotlin里面ArrayList不能被Parcelable?

于是带着问题,又试了将images类型分别改为:List、MutableList,结果发现只有当定义成List类型的时候,才会自动生成images变量的Parcelable代码,如下:


    class DemoBean() : Parcelable {
    var name: String? = null
    var images: List<String>? = null

    constructor(parcel: Parcel) : this() {
        name = parcel.readString()
        images = parcel.createStringArrayList()//看这里!!!!
    }

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(name)
        parcel.writeStringList(images)//看这里!!!!
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<DemoBean> {
        override fun createFromParcel(parcel: Parcel): DemoBean {
            return DemoBean(parcel)
        }

        override fun newArray(size: Int): Array<DemoBean?> {
            return arrayOfNulls(size)
        }
    }

}

虽然说在kotlin里,这里定义成List类型也是可以的,因为ArrayList是继承自MutableList,而MutableList是继承自List,但是List里却没有常用的clear、addAll等方法,在使用到这个List的时候需要强制类型转换,不是很方便。

如果定义成ArrayList不会自动生成Parcelable代码,那手动加上行不行呢?于是带着疑问将images类型改为最开始的ArrayList,上面images变量生成的Parcelable代码保持不变,完整代码如下:


class DemoBean() : Parcelable {
    var name: String? = null
    var images: ArrayList<String>? = null//看这里!!!!

    constructor(parcel: Parcel) : this() {
        name = parcel.readString()
        images = parcel.createStringArrayList()//看这里!!!!
    }

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(name)
        parcel.writeStringList(images)//看这里!!!!
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<DemoBean> {
        override fun createFromParcel(parcel: Parcel): DemoBean {
            return DemoBean(parcel)
        }

        override fun newArray(size: Int): Array<DemoBean?> {
            return arrayOfNulls(size)
        }
    }

}

试了一下发现ArrayList手动实现Parcelable完全没问题,跳转Activity后数据也能够恢复,所以总结下来那就只能是Android Studio的bug了。
如果手写Parcelable代码实现,则需要注意:
1、如果ArrayList里的对象是String类型的:

class DemoBean() : Parcelable {
    var images: ArrayList<String>? = null

    constructor(parcel: Parcel) : this() {
        images = parcel.createStringArrayList()
    }

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeStringList(images)
    }

2、如果ArrayList里的对象是自定义,则该对象也要实现Parcelable:


class DemoBean() : Parcelable {
    var images: ArrayList<OtherDataBean>? = null

    constructor(parcel: Parcel) : this() {
        images = parcel.createTypedArrayList(OtherDataBean.CREATOR)
    }

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeTypedList(images)
    }

3、还要注意各个变量的顺序问题,比如变量a和b,在writeToParcel方法里,a在b的前面write,而constructor里b却在a的前面恢复就不行,数据不能被正确恢复

当然还有更简便的方法,但目前只是实验性的功能,纯Kotlin开发还可以,混合开发可能会出现编译不通过找不到CREATOR问题

app的build.gradle里添加如下配置,开启kotlin实验性功能


    android{
    ...
    androidExtensions {
        experimental = true
    }
    ...
}

然后在类名上面添加@Parcelize注解就可以了,如果出现Link提示则再在上面加上@SuppressLint(“ParcelCreator”)忽略警告

@SuppressLint("ParcelCreator")//这句视情况而定,我这个AS版本没有报错
@Parcelize
class DemoBean() : Parcelable {
    var images: ArrayList<OtherDataBean>? = null
}

我的Android Studio版本号是:3.4.2
kotlin版本号是:1.3.41

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值