Kotlin数据类中的函数作为参数导致parceling错误

时间:2018-03-20 12:10:35

标签: android lambda kotlin kotlin-android-extensions

我在Kotlin帽子中有一个数据类正在使用@Parcelize注释来轻松实现分片化。事我现在想把一个函数传递给这个类,我真的不知道如何在parceling期间不考虑这个函数。

这是我的数据类:

@Parcelize
data class GearCategoryViewModel(
        val title: String,
        val imageUrl: String,
        val categoryId: Int,
        val comingSoon: Boolean,
        @IgnoredOnParcel val onClick: (gearCategoryViewModel: GearCategoryViewModel) -> Unit
) : DataBindingAdapter.LayoutViewModel(R.layout.gear_category_item), Parcelable

我尝试使用@IgnoredOnParcel@Transient但没有成功。

这是我得到的编译错误:

  

错误:(20,39)'Parcelize'不直接支持Type。如果要使用'writeValue()'

序列化参数类型,请使用'@RawValue'注释参数类型

@RawValue注释也不起作用。

4 个答案:

答案 0 :(得分:5)

只需将lambda转换为可序列化的对象,然后从

创建对象
@Parcelize
data class GearCategoryViewModel(
        val title: String,
        val imageUrl: String,
        val categoryId: Int,
        val comingSoon: Boolean,
        @IgnoredOnParcel val onClick: Serializable
) : DataBindingAdapter.LayoutViewModel(R.layout.gear_category_item), Parcelable {

    fun onClicked() = onClick as (gearCategoryViewModel: GearCategoryViewModel) -> Unit

    companion object {
        fun create(
                title: String,
                imageUrl: String,
                categoryId: Int,
                comingSoon: Boolean,
                onClick: (gearCategoryViewModel: GearCategoryViewModel) -> Unit
        ): GearCategoryViewModel = GearCategoryViewModel(
                title,
                imageUrl,
                categoryId,
                comingSoon,
                onClick as Serializable
        )
    }
}

答案 1 :(得分:0)

我知道这不是一个真正的答案,但我会这样做。用这样的类替换你的函数:

open class OnClick() : Parcelable {

    companion object {
        @JvmStatic
        fun fromLambda(func: (GearCategoryViewModel) -> Unit) = object : OnClick() {
            override fun invoke(param: GearCategoryViewModel) = func(param)
        }

        @JvmField
        val CREATOR = object : Parcelable.Creator<OnClick> {
            override fun createFromParcel(parcel: Parcel) = OnClick(parcel)

            override fun newArray(size: Int) = arrayOfNulls<OnClick>(size)
        }
    }

    constructor(parcel: Parcel) : this()

    open operator fun invoke(param: GearCategoryViewModel) {
        throw UnsupportedOperationException("This method needs to be implemented")
    }

    override fun writeToParcel(parcel: Parcel, flags: Int) = Unit

    override fun describeContents() = 0
}

并像这样使用它:

val onClick = OnClick.fromLambda { vm -> /* do something*/ }
onClick(viewModel);

答案 2 :(得分:0)

这个问题的前提真的没有道理。

如果不序列化该对象的所有属性,则不能反序列化该对象。

如果将onClick进行反序列化,您似乎希望将null设为{{1}},但是即使有可能,它也会抛出NPE,因为此属性未标记为可空。

考虑更改体系结构,以便仅序列化简单对象(PO​​JO或数据类),而不序列化函数。

答案 3 :(得分:0)

@Parcelize
data class GearCategoryViewModel(
        val title: String,
        val imageUrl: String,
        val categoryId: Int,
        val comingSoon: Boolean,
        val onClick: @RawValue (gearCategoryViewModel: GearCategoryViewModel) -> Unit
) : DataBindingAdapter.LayoutViewModel(R.layout.gear_category_item), Parcelable

使用@RawValue和onClick参数。