Kotlin Data Class出现异常结果:含@Parcelize的MemberCard类问题咨询
Hey there, let's dig into why your @Parcelize-annotated MemberCard data class is throwing exceptions. I’ve run into most of these issues myself, so here’s a step-by-step breakdown of what to check and fix:
1. Double-Check Parcelize Plugin & Dependencies
If you haven’t configured the Kotlin Parcelize plugin properly, that’s almost certainly the first issue to resolve:
- In your app-level
build.gradle(orbuild.gradle.kts), confirm the plugin is applied:// Groovy syntax plugins { id 'kotlin-parcelize' } // Kotlin DSL syntax plugins { id("kotlin-parcelize") } - Also, make sure your Kotlin version is up-to-date—older versions have known bugs with complex data classes using
@Parcelize.
2. Validate Your Parent Interface Setup
Your MemberCard uses override on fields like MembershipNumber and ExpirationDate, which means it’s inheriting from a parent interface (let’s say something like BaseMembership). For @Parcelize to work smoothly:
- The parent interface must extend
Parcelable - All overridden properties need to be included in parcelization. If the parent has abstract properties,
@Parcelizeshould handle them automatically, but double-check none of these fields are markedtransient(that would exclude them from serialization entirely).
3. Fix the Date Type (It’s Not Parcelable by Default!)
The ExpirationDate field uses Date, which isn’t a default supported type for @Parcelize. Kotlin’s Parcelize only handles basic types, collections of supported types, and other Parcelable classes out of the box. You’ve got two solid fixes here:
Option 1: Use a Timestamp (Simplest Approach)
Replace Date with a Long (store the timestamp) and convert back to Date when you need it:
@Parcelize data class MemberCard( val PartnerMembershipId: Int, override var MembershipNumber: String? = null, override var Name: String? = null, var MemberImgUrl: String? = null, val TextColorHex: String? = null, override var ExpirationDate: Long? = null, // Store timestamp instead of Date override var Issuer: String, var Notifications: kotlin.Int? = null, override var BarcodeType: kotlin.String? = null, override var Barcode: kotlin.String? = null, val IsPartnerCard: Boolean, val Status : String ) : BaseMembership { // Replace with your actual parent interface // Helper method to convert back to Date fun getExpirationDateAsDate(): Date? = ExpirationDate?.let { Date(it) } }
Option 2: Create a Custom Parceler for Date
If you want to keep using Date, make a custom parceler to handle serialization:
// Define the parceler object DateParceler : Parceler<Date> { override fun create(parcel: Parcel): Date = Date(parcel.readLong()) override fun Date.write(parcel: Parcel, flags: Int) = parcel.writeLong(time) } // Apply it to your data class @Parcelize @TypeParceler<Date, DateParceler>() data class MemberCard( // ... all your existing fields including ExpirationDate: Date? = null ) : BaseMembership
4. Check Nullable & Val/Var Consistency
@Parcelizeworks with nullable fields, but ensure all non-nullvalfields (likePartnerMembershipId,Issuer,IsPartnerCard,Status) are always initialized when creating aMemberCardinstance—they don’t have default values, so passing null here will throw an NPE.- If you’re seeing null-related exceptions, double-check that you’re not passing null to these required non-null fields.
5. Make Sure All Serialized Fields Are in the Primary Constructor
@Parcelize only serializes properties defined in the data class’s primary constructor. If you’ve added any properties outside of it (like in a secondary constructor or as class-level properties), they won’t be parcelized. Move any fields that need to be saved/restored into the primary constructor.
6. Test Parcelization Manually to Pinpoint the Issue
To figure out exactly which field is causing the problem, test parceling and unparceling directly in debug code or a unit test:
// Create a test instance of MemberCard val testCard = MemberCard( PartnerMembershipId = 123, Issuer = "Coffee Shop Co.", IsPartnerCard = true, Status = "ACTIVE" ) // Parcel the object val parcel = Parcel.obtain() testCard.writeToParcel(parcel, 0) parcel.setDataPosition(0) // Reset parcel to read from the start // Unparcel it val unparceledCard = MemberCard.CREATOR.createFromParcel(parcel) // Compare fields to spot inconsistencies check(testCard.PartnerMembershipId == unparceledCard.PartnerMembershipId) check(testCard.Issuer == unparceledCard.Issuer) // Add checks for other fields to see which one breaks
This will help you isolate exactly which field is causing the exception (e.g., if ExpirationDate is the culprit, the check for that field will fail or throw an error).
内容的提问来源于stack exchange,提问作者Andrew Matiuk

