如何从kotlin-android-extensions中将Parcel.readTypedList()与@Parcelize一起使用?

时间:2018-08-11 11:48:15

标签: android kotlin parcelable kotlin-android-extensions

在View中实现基于Parcelable的状态持久化时遇到了问题。即,因为我需要像这样实现BaseSavedState的方法:

class SavedState : BaseSavedState {
    lateinit var myList: ArrayList<MyParcelable>

    constructor(superState: Parcelable) : super(superState) {}

    private constructor(parcel: Parcel) : super(parcel) {
        val listSize = parcel.readInt()
        val list = ArrayList<MyParcelable>(listSize)
        this.myList = parcel.readTypedList(list, /* needs MyParcelable.CREATOR */ )
    }

    override fun writeToParcel(out: Parcel, flags: Int) {
        super.writeToParcel(out, flags)
        out.writeInt(myList.size())
        out.writeTypedList(myList)
    }

    companion object {
        @JvmField
        val CREATOR: Parcelable.Creator<SavedState> = object : Parcelable.Creator<SavedState> {
            override fun createFromParcel(`in`: Parcel): SavedState {
                return SavedState(`in`)
            }

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

但是,正如您所看到的,我似乎无法使用Parcel.readTypedList(),因为它既需要类型列表,又需要可包裹的CREATOR字段!

类标记为:

@Parcelize
data class MyParcelable(val someData: String): Parcelable {
}

没有创建者,实际上,如果您尝试实现,它会说:

  

不允许使用“ CREATOR”定义。请改用“包裹”辅助对象。

想要一个包裹伴侣对象,我需要一个创造者!

我也不想手工编写Parcelable实现,因此我可能只是将其设置为Serializable,就像“随便什么”。


有人偶然知道如何将Parcel.readTypedList()与带有注释的@Parcelize的Kotlin数据类一起使用吗?

2 个答案:

答案 0 :(得分:3)

就像您提到的https://youtrack.jetbrains.com/issue/KT-19853一样,这是Parcelize插件上的错误,可以通过反射或实际上解决,您可以拥有Java的代理类,因为您可以访问Java中的CREATOR字段没有任何问题。

我为所有创建者创建了一个util java 类,然后进行了指向该创建者的kotlin扩展

Java

@NonNull
public static Parcelable.Creator<Blah> getBlahCreator() {
    return Blah.CREATOR;
}

科特琳

val Blah.Companion.CREATOR: Parcelable.Creator<Blah>
 get() = UtilClass.getBlahCreator()

现在我可以在任何地方访问Blah.CREATOR了!而且,在可预见的将来修复了该错误之后,可以将这两个具有所有创建者和扩展名的类删除,并且可以按预期工作,而无需对其他使用CREATOR的类进行任何编辑

对我来说,这比反射解决方案好得多!但是无论哪种方式,它们都令人恶心,我希望这个错误能够尽快得到解决!

答案 1 :(得分:1)

针对该问题进行了投票,因为我在一个班级中遇到了相同的问题,但由于我是新用户而无法看到。 我使用了以下替代方法,(readArrayList)尽管有细微差别

readTypedList
arrayListOf<YourParcelableClass>().apply { parcel.readArrayList(YourParcelableClass::class.java.classLoader) }

感谢接受的解决方案,但不确定为什么,即使在Java类文件中,我也无法读取CREATOR字段。