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
)
}
}
@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を使用します。
質問の前提は実際には意味がありません。
すべてのプロパティをシリアル化しない場合、このオブジェクトを逆シリアル化することはできません。
これが逆シリアル化されている場合はonClick
をnull
にしたいようですが、それが可能であったとしても、このプロパティはnull許容としてマークされていないため、NPEがスローされます。
関数ではなく単純なオブジェクト(POJOまたはデータクラス)のみをシリアル化するようにアーキテクチャを変更することを検討してください。
私はこれが正確に本当の答えではないことを知っていますが、私はこのようにします。関数を次のようなクラスに置き換えます。
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);