2012-12-21 79 views
13

對於我的Android應用程序,我得到幾個數據編出的錯誤,雖然我覺得我做到了這一點,需要通過Parcelable s到正確保存和加載對象的一切。你能告訴我我的代碼有什麼問題嗎?解組錯誤使用自定義parcelable類

錯誤1:

java.lang.RuntimeException: Unable to start activity ComponentInfo 
Caused by: java.lang.RuntimeException: Parcel [email protected]: Unmarshalling unknown type code 6619241 at offset 1372 
at android.os.Parcel.readValue(Parcel.java:1922) 
at android.os.Parcel.readMapInternal(Parcel.java:2094) 
at android.os.Bundle.unparcel(Bundle.java:223) 
at android.os.Bundle.getParcelable(Bundle.java:1158) 
at android.app.Activity.onCreate(Activity.java:860) 
at my.app.package.PlayComputer.onCreate(PlayComputer.java:1012) 
at android.app.Activity.performCreate(Activity.java:4465) 

MyActivity 1012行是在調用super.onCreate(savedInstanceState);ActivityonCreate()

protected void onSaveInstanceState(Bundle savedInstanceState) { 
    if (myObject == null) { 
     savedInstanceState.putParcelable("myObject", null); 
    } 
    else { 
     savedInstanceState.putParcelable("myObject", myObject); 
    } 
    savedInstanceState.putInt(...); 
    savedInstanceState.putString(...); 
    savedInstanceState.putBoolean(...); 
    super.onSaveInstanceState(savedInstanceState); 
} 

myObjectMyObject類具有下列方法:

public void writeToParcel(Parcel out, int flags) { 
    out.writeIntArray(...); 
    out.writeInt(...); 
    out.writeStringArray(...); 
    out.writeString(...); 
    out.writeParcelableArray(..., flags); 
} 

public static final Parcelable.Creator<MyObject> CREATOR = new Parcelable.Creator<MyObject>() { 
    public MyObject createFromParcel(Parcel in) { 
     try { 
      if (in == null) { 
       return null; 
      } 
      else { 
       return new MyObject(in); 
      } 
     } 
     catch (Exception e) { 
      return null; 
     } 
    } 
    public MyObject[] newArray(int size) { 
     return new MyObject[size]; 
    } 
}; 

private MyObject(Parcel in) { 
    in.readIntArray(...); 
    ... = in.readInt(); 
    in.readStringArray(...); 
    ... = in.readString(); 
    ... = (OtherObject[]) in.readParcelableArray(OtherObject.class.getClassLoader()); 
} 

錯誤2:

java.lang.RuntimeException: Unable to start activity ComponentInfo 
Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: 
at android.os.Parcel.readParcelable(Parcel.java:1971) 
at android.os.Parcel.readValue(Parcel.java:1859) 
at android.os.Parcel.readMapInternal(Parcel.java:2099) 
at android.os.Bundle.unparcel(Bundle.java:223) 
at android.os.Bundle.getParcelable(Bundle.java:1158) 
at android.app.Activity.onCreate(Activity.java:905) 
at my.app.package.PlayComputer.onCreate(SourceFile:1012) 

相同文件和類。

錯誤3:

java.lang.RuntimeException: Unable to start activity ComponentInfo 
Caused by: java.lang.RuntimeException: Parcel [email protected]: Unmarshalling unknown type code 7340149 at offset 1276 
at android.os.Parcel.readValue(Parcel.java:1913) 
at android.os.Parcel.readMapInternal(Parcel.java:2083) 
at android.os.Bundle.unparcel(Bundle.java:208) 
at android.os.Bundle.getParcelable(Bundle.java:1100) 
at my.app.package.PlayComputer.onCreate(SourceFile:1111) 

這次,使線(1111)是下述之一:

myObject = (MyObject) savedInstanceState.getParcelable("myObject"); 
+0

GameState(Parcel in)構造函數是一個錯字,而你打算寫一個MyObject(Parcel in)構造函數嗎? – fedepaol

+0

@fedepaol:對,對不起! – caw

+0

你是否在構造函數中分別創建數組對象? 'readXXXArray()'方法需要傳入一個完全初始化的數組實例。您可以使用'createXXXArray()'方法將該數組的一個新實例返回給您。 – Devunwired

回答

37

Android有兩個不同的類加載器:框架類加載器(它知道如何加載安卓類)和APK類加載器(它知道如何裝載你的代碼)。該APK類加載器具有框架類加載器設置爲其父,這意味着它也可以裝載Android的類。

錯誤#2很可能被捆綁使用框架的classloader所以它不知道你的類引起的。我認爲,當Android的需要,以保存捆綁,並(在後臺運行時內存不足,例如)以後恢復它會發生這種情況。您可以通過在軟件包上設置APK classloader來解決此問題:

savedInstanceState.setClassLoader(getClass()。getClassLoader());

錯誤#1和#3更神祕,你可能寫空值writeToParcel()? Android恐怕不是那麼喜歡它。

+0

謝謝! 'savedInstanceState.setClassLoader(getClass()。getClassLoader());'看起來不錯,但恐怕我只能在一個類中調用它。如果我必須將來自多個班級的物品放入該「捆綁」中,該怎麼辦?什麼課程可以打電話給? – caw

+0

此外,一些更改,似乎現在問題得到解決:http://stackoverflow.com/questions/13997550/unmarshalling-errors-in-android-app-with-custom-parcelable-classes#comment19498428_13997695你能想象這種閱讀物體的方式是什麼導致了問題? – caw

+1

這將適用於所有類,如getClass()。getClassLoader()將檢索APK類加載器(它可以加載所有類)。 使用readXXXArray()進行讀取時,您傳遞了哪些數組?你怎麼知道他們的長度是正確的? createTypedArray()等人不會寫/讀類型信息,這意味着類加載器並不真正涉及。 – alexanderblom

2

通過它的外觀,所述createFromParcelnewArray應該重寫像這樣:

public static final Parcelable.Creator<MyObject> CREATOR = new Parcelable.Creator<MyObject>() { 
    @Override 
    public MyObject createFromParcel(Parcel in) { 
     MyObject myObj = new MyObject(); 
     myObj.intArray = in.readIntArray(...); 
     myObj.intValue = in.readInt(...); 
     // .... 
     // IN THE SAME ORDER THAT IS WRITTEN OUT AS PER writeToParcel! 
     // 
     return myObj; 
    } 
    @Override 
    public MyObject[] newArray(int size) { 
     return new MyObject[size]; 
    } 
}; 

編輯:

我忘了提及上面的工作,應該有一個空的構造函數!

public MyObject(){} 
+0

謝謝!這不正是我在做什麼?我只是使用構造函數'MyObject(in)'來使事情更清晰。好吧,也許你沒有看到這個,因爲我的拼寫錯誤,現在已經得到糾正。 – caw

+0

我只能想到,也許應該有一個空的構造函數,修改了答案...... – t0mm13b

+0

請驗證您是'@ Override'這兩個方法'describeContents()'和'writeToParcel()': ) – t0mm13b

0

之前從捆組類加載器

bundle.setClassLoader(的getClass()讀取。getClassLoader());

這節省了我的時間!