【问题标题】:How to use Parcel.readTypedList() along with @Parcelize from kotlin-android-extensions?如何使用 Parcel.readTypedList() 以及来自 kotlin-android-extensions 的 @Parcelize?
【发布时间】:2018-08-11 11:48:14
【问题描述】:

我在视图中实现基于 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(),因为它需要类型列表和 parcelable 的 CREATOR 字段!

类标记为:

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

没有CREATOR,其实如果你尝试实现,它会说:

'CREATOR' 定义是不允许的。请改用“Parceler”伴随对象。

我确实想要 Parceler 伴侣对象,我需要一个 CREATOR!

我也有点不想手动编写 Parcelable 实现,所以我可能只是将它设为 Serializable 并像“随便”一样。


有没有人偶然知道如何将Parcel.readTypedList()@Parcelize-annotated Kotlin 数据类一起使用?

【问题讨论】:

标签: android kotlin parcelable kotlin-android-extensions


【解决方案1】:

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

我为所有创建者创建了一个 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的其他类中进行任何编辑

这对我来说比反射解决方案好得多!但无论哪种方式,它们都很恶心,我希望这个错误可以尽快修复!

【讨论】:

  • 我的意思是,如果您可以像那样访问创建者字段,那么您可以在 Java 中公开一个 Helper 类,该类具有返回 CREATOR 实例的单个函数。我不需要复制对象,我只需要它的创建者:p 当我靠近 PC 时我会检查这个
  • 没想到val Blah.Companion.CREATOR,喜欢!谢谢!
  • kotlin 版本的 getBlahCreator() 里面的代码是什么样子的?
  • @AndrewKelly 文件名为UtilClass.java,内容为class UtilClass { @NonNull public static Parcelable.Creator&lt;Blah&gt; getBlahCreator() { return Blah.CREATOR; } }
【解决方案2】:

赞成这个问题,因为我在一堂课中遇到了同样的问题,但由于我是新用户,所以它不可见。 我使用了下面的替代方法,(readArrayList)虽然它有细微的差别

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

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

【讨论】:

  • 似乎比答案更适合新问题或评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-03
  • 1970-01-01
  • 2022-07-06
  • 2018-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多