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

Epi*_*rce 3 android parcelable kotlin 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)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

类标记为:

@Parcelize
data class MyParcelable(val someData: String): Parcelable {
}
Run Code Online (Sandbox Code Playgroud)

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

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

想要一个Parceler同伴对象,我需要一个CREATOR!

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


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

小智 7

https://github.com/JetBrains/kotlin/commit/fc013c6b9f5f3083d06385803ff687dc9a6ab4f0#

从Kotlin 1.6.21开始,我们可以使用parcelableCreator ()

import kotlinx.parcelize.parcelableCreator

val dataClass = TestDataClass("someValue")
val creator = parcelableCreator<TestDataClass>()
val parcel: Parcel? = null
parcel?.createTypedArrayList(creator) // Will compile
Run Code Online (Sandbox Code Playgroud)


Ahm*_*azy 6

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

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

爪哇

@NonNull
public static Parcelable.Creator<Blah> getBlahCreator() {
    return Blah.CREATOR;
}
Run Code Online (Sandbox Code Playgroud)

科特林

val Blah.Companion.CREATOR: Parcelable.Creator<Blah>
 get() = UtilClass.getBlahCreator()
Run Code Online (Sandbox Code Playgroud)

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

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