web-dev-qa-db-ja.com

Kotlinデータクラスの引数としての関数は、パーセルエラーにつながります

Kotlinハットにデータクラスがあり、簡単に区画化するために@Parcelizeアノテーションを使用しています。このクラスに関数を渡したいのですが、パーセル処理中に関数が考慮されないようにする方法がわかりません。

これは私のデータクラスです:

@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」で直接サポートされていません。 'writeValue()'を使用してシリアル化する場合は、パラメータータイプに '@RawValue'で注釈を付けます。

また、この@RawValueアノテーションも機能しません。

ラムダをシリアライズ可能にキャストし、からオブジェクトを作成するだけです

@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
        )
    }
}
6
Artur Dumchev
@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

OnClickパラメーターで@RawValueを使用します。

0
apurv thakkar

質問の前提は実際には意味がありません。

すべてのプロパティをシリアル化しない場合、このオブジェクトを逆シリアル化することはできません。

これが逆シリアル化されている場合はonClicknullにしたいようですが、それが可能であったとしても、このプロパティはnull許容としてマークされていないため、NPEがスローされます。

関数ではなく単純なオブジェクト(POJOまたはデータクラス)のみをシリアル化するようにアーキテクチャを変更することを検討してください。

0
Andrew Gallasch

私はこれが正確に本当の答えではないことを知っていますが、私はこのようにします。関数を次のようなクラスに置き換えます。

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);
0
TheKarlo95