4

我遇到了一些Parcelable自定義類的問題,我正在使用這個自定義類來安裝Android應用程序,而我已經設法以非常奇怪的方式解決這個問題。Android Parcelable訂單

我只在幾個特定的​​情況下從一個parcelable讀取時發生了崩潰(這導致我認爲我的實現並非完全錯誤)。

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.worldcraze.worldcraze/com.worldcraze.worldcraze.AdActivity}: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: Surface Book 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
at android.app.ActivityThread.-wrap11(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:5417) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

Caused by: android.os.BadParcelableException: ClassNotFoundException when  unmarshalling: Surface Book 
at android.os.Parcel.readParcelableCreator(Parcel.java:2432) 
at android.os.Parcel.readParcelable(Parcel.java:2358) 
at com.worldcraze.worldcraze.API.Model.TransportOffer.<init>  (TransportOffer.java:33) 
at  com.worldcraze.worldcraze.API.Model.TransportOffer$1.createFromParcel(TransportO ffer.java:43) 
    at  com.worldcraze.worldcraze.API.Model.TransportOffer$1.createFromParcel(TransportO ffer.java:40) 
at android.os.Parcel.createTypedArray(Parcel.java:2167) 
at com.worldcraze.worldcraze.API.Model.Ad.<init>(Ad.java:42) 
at com.worldcraze.worldcraze.API.Model.Ad$1.createFromParcel(Ad.java:52) 
at com.worldcraze.worldcraze.API.Model.Ad$1.createFromParcel(Ad.java:49) 
at android.os.Parcel.readParcelable(Parcel.java:2367) 
at android.os.Parcel.readValue(Parcel.java:2264) 
at android.os.Parcel.readArrayMapInternal(Parcel.java:2614) 
at android.os.BaseBundle.unparcel(BaseBundle.java:221) 
at android.os.Bundle.getParcelable(Bundle.java:786) 
at android.content.Intent.getParcelableExtra(Intent.java:5377) 
at com.worldcraze.worldcraze.AdActivity.onCreate(AdActivity.java:57) 
at android.app.Activity.performCreate(Activity.java:6251) 
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) 
... 9 more 

這是我原來實行的崩潰是在(Ad.java)存在的模型

public class Ad implements Parcelable { 

public String    author; 
public String    transporter; 
public Image    cover_urls; 
public String    details; 
public String    id; 
public int     item_size; 
public String    object_name; 
public Money    tips; 
public Money    price; 
public Location   where_to_buy; 
public String    resource_uri; 
public Location   where_to_deliver; 
public Permissions   permissions; 
public TransportOffer[] transport_offers; 
public float    fees_lemonway_CB; 
public String    validation_code; 
public Date    creation_dtime; 
public String    accepted_transport_offer_id; 

protected Ad(Parcel in) { 
    author   = in.readString(); 
    transporter  = in.readString(); 
    details   = in.readString(); 
    id    = in.readString(); 
    item_size  = in.readInt(); 
    object_name  = in.readString(); 
    resource_uri  = in.readString(); 
    cover_urls  = in.readParcelable(Image.class.getClassLoader()); 
    tips    = in.readParcelable(Money.class.getClassLoader()); 
    price   = in.readParcelable(Money.class.getClassLoader()); 
    permissions  = in.readParcelable(Permissions.class.getClassLoader()); 
    transport_offers = in.createTypedArray(TransportOffer.CREATOR); 
    where_to_buy  = in.readParcelable(Location.class.getClassLoader()); 
    where_to_deliver = in.readParcelable(Location.class.getClassLoader()); 
    fees_lemonway_CB = in.readFloat(); 
    validation_code = in.readString(); 
    creation_dtime = (Date) in.readSerializable(); 
    accepted_transport_offer_id = in.readString(); 
} 

public static final Creator<Ad> CREATOR = new Creator<Ad>() { 
    @Override 
    public Ad createFromParcel(Parcel in) { 
     return new Ad(in); 
    } 

    @Override 
    public Ad[] newArray(int size) { 
     return new Ad[size]; 
    } 
}; 

@Override 
public int describeContents() { 
    return 0; 
} 

@Override 
public void writeToParcel(Parcel dest, int flags) { 
    dest.writeString(author); 
    dest.writeString(transporter); 
    dest.writeString(details); 
    dest.writeString(id); 
    dest.writeInt(item_size); 
    dest.writeString(object_name); 
    dest.writeString(resource_uri); 
    dest.writeParcelable(cover_urls, flags); 
    dest.writeParcelable(tips, flags); 
    dest.writeParcelable(price, flags); 
    dest.writeParcelable(permissions, flags); 
    dest.writeTypedArray(transport_offers, flags); 
    dest.writeParcelable(where_to_buy, flags); 
    dest.writeParcelable(where_to_deliver, flags); 
    dest.writeFloat(fees_lemonway_CB); 
    dest.writeString(validation_code); 
    dest.writeSerializable(creation_dtime); 
    dest.writeString(accepted_transport_offer_id); 
} 

}的

我設法通過改變讀取爲了解決該問題/寫一些Parcelable屬性。 我現在正在讀/寫where_to_buy和where_to_deliver在cover_urls之前似乎已經解決了問題。

where_to_buy  = in.readParcelable(Location.class.getClassLoader()); 
    where_to_deliver = in.readParcelable(Location.class.getClassLoader()); 
    cover_urls  = in.readParcelable(Image.class.getClassLoader()); 
    tips    = in.readParcelable(Money.class.getClassLoader()); 
    price   = in.readParcelable(Money.class.getClassLoader()); 
    permissions  = in.readParcelable(Permissions.class.getClassLoader()); 
    transport_offers = in.createTypedArray(TransportOffer.CREATOR); 

(在writeToParcel中的順序是相同的,我只是通過不粘貼它在這裏保存幾行)。

這個奇怪的修復工作就像一個魅力,我不知道爲什麼。

有沒有人遇到類似的東西或知道爲什麼包裝/拆包的順序會影響結果?

乾杯!

回答

4

這不是一個不正常的行爲。如果你明白它在內部是如何工作的,你就會明白爲什麼你會遇到異常。

序列化基本上是按字節順序寫入的。因此,您按照某種順序(例如4-16-1-2)寫入了一些可變長度的字節,然後您從Parcel讀取字節。

在從Parcel讀取數據時,嘗試讀取例如16字節,但實際上已經寫了4個字節,這就是爲什麼會發生崩潰。

閱讀的順序應該與寫作的順序一致,否則當你嘗試閱讀時,最終會出現這種情況。 16個字節,但實際上你的變量是4個字節。