问题解组的问题

我有几个类实现Parcelable ,其中一些类包含对方作为属性。 我将这些类编组为一个包,以在活动之间传递它们。 将它们编组到这个包可以正常工作,但是当我尝试解除它们时,我得到以下错误:

... AndroidRuntime E Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: schemas.Arrivals.LocationType AndroidRuntime E at android.os.Parcel.readParcelable(Parcel.java:1822) AndroidRuntime E at schemas.Arrivals.LayoverType.<init>(LayoverType.java:121) AndroidRuntime E at schemas.Arrivals.LayoverType.<init>(LayoverType.java:120) AndroidRuntime E at schemas.Arrivals.LayoverType$1.createFromParcel(LayoverType.java:112) AndroidRuntime E at schemas.Arrivals.LayoverType$1.createFromParcel(LayoverType.java:1) AndroidRuntime E at android.os.Parcel.readTypedList(Parcel.java:1509) AndroidRuntime E at schemas.Arrivals.BlockPositionType.<init>(BlockPositionType.java:244) AndroidRuntime E at schemas.Arrivals.BlockPositionType.<init>(BlockPositionType.java:242) AndroidRuntime E at schemas.Arrivals.BlockPositionType$1.createFromParcel(BlockPositionType.java:234) AndroidRuntime E at schemas.Arrivals.BlockPositionType$1.createFromParcel(BlockPositionType.java:1) ... 

LayoverType类(失败的地方):

 public class LayoverType implements Parcelable { protected LocationType location; protected long start; protected long end; public LayoverType() {} public LocationType getLocation() { return location; } public void setLocation(LocationType value) { this.location = value; } public long getStart() { return start; } public void setStart(long value) { this.start = value; } public long getEnd() { return end; } public void setEnd(long value) { this.end = value; } // ********************************************** // for implementing Parcelable // ********************************************** @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeParcelable(location, flags); dest.writeLong(start); dest.writeLong(end ); } public static final Parcelable.Creator<LayoverType> CREATOR = new Parcelable.Creator<LayoverType>() { public LayoverType createFromParcel(Parcel in) { return new LayoverType(in); } public LayoverType[] newArray(int size) { return new LayoverType[size]; } }; private LayoverType(Parcel dest) { location = (LocationType) dest.readParcelable(null); // it's failing here start = dest.readLong(); end = dest.readLong(); } } 

这里是LocationType类:

 public class LocationType implements Parcelable { protected int locid; protected String desc; protected String dir; protected double lat; protected double lng; public LocationType() {} public int getLocid() { return locid; } public void setLocid(int value) { this.locid = value; } public String getDesc() { return desc; } public void setDesc(String value) { this.desc = value; } public String getDir() { return dir; } public void setDir(String value) { this.dir = value; } public double getLat() { return lat; } public void setLat(double value) { this.lat = value; } public double getLng() { return lng; } public void setLng(double value) { this.lng = value; } // ********************************************** // for implementing Parcelable // ********************************************** @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt (locid); dest.writeString(desc ); dest.writeString(dir ); dest.writeDouble(lat ); dest.writeDouble(lng ); } public static final Parcelable.Creator<LocationType> CREATOR = new Parcelable.Creator<LocationType>() { public LocationType createFromParcel(Parcel in) { return new LocationType(in); } public LocationType[] newArray(int size) { return new LocationType[size]; } }; private LocationType(Parcel dest) { locid = dest.readInt (); desc = dest.readString(); dir = dest.readString(); lat = dest.readDouble(); lng = dest.readDouble(); } } 

更新2 :据我可以告诉它在下面的代码(来自Parcel的源代码 )失败:

 Class c = loader == null ? Class.forName(name) : Class.forName(name, true, loader); 

为什么找不到课程? 它既存在又实现了Parcelable

因为这在“答案”中没有回答,但是在评论中我会发表一个答案:由于@ Max-Gontar指出你应该使用LocationType.class.getClassLoader()来获得正确的ClassLoader,并且摆脱ClassNotFoundexception,即:

in.readParceleable(LocationType.class.getClassLoader());

我有与以下设置相同的问题:某些处理程序创build一个消息,并通过Messenger发送到远程服务。

该消息包含一个包裹,我把我的Parcelable后裔:

 final Message msg = Message.obtain(null, 0); msg.getData().putParcelable("DOWNLOADFILEURLITEM", downloadFileURLItem); messenger.send(msg); 

当远程服务试图不encryption时,我也有同样的例外。 就我而言,我曾经监督过远程服务的确是一个独立的操作系统进程。 因此,我必须设置当前的类加载器在服务端的非编程过程中使用:

 final Bundle bundle = msg.getData(); bundle.setClassLoader(getClassLoader()); DownloadFileURLItem urlItem = (DownloadFileURLItem) bundle.getParcelable("DOWNLOADFILEURLITEM"); 

Bundle.setClassLoader设置用于加载适当的Parcelable类的类加载器。 在远程服务中,您需要将其重置为当前的类加载器。

我发现问题是我没有将我的应用程序ClassLoader传递给解组函数:

 in.readParceleable(getContext().getClassLoader()); 

而不是:

 in.readParceleable(null); 

要么

 in.readParceleable(MyClass.class.getClassLoader()); 

只要在这里加上我的2分钱,因为我在这个问题上失去了半天多的时间。 如果不按照完全相同的顺序放置写入方法和读取方法,则可能会出现此错误。 例如,以下将是错误的:

  @Override // Order: locid -> desc -> lat -> dir -> lng public void writeToParcel(Parcel dest, int flags) { dest.writeInt (locid); dest.writeString(desc); dest.writeDouble(lat); dest.writeString(dir); dest.writeDouble(lng); } // Order: locid -> desc -> dir -> lat -> lng private LocationType(Parcel dest) { locid = dest.readInt(); desc = dest.readString(); dir = dest.readString(); lat = dest.readDouble(); lng = dest.readDouble(); } 

顺便提一下,作者正确地做了这件事,但有一天它可能会帮助别人。

我对Parcelable不是很熟悉,但是如果它是Serialization之类的东西,每次调用写一个实现接口的对象都会导致对writeToParcel()的recursion调用。 因此,如果沿着调用堆栈的某些内容失败或写入空值,那么启动调用的类可能无法正确构build。

尝试:从第一次调用writeToParcel()开始,通过所有类跟踪writeToParcel()调用堆栈,并validation所有值是否正确发送。

我也得到了ClassNotFoundException,并发布了我的解决schemebc这里的答案让我走向了正确的方向。 我的情况是,我有嵌套parcelable对象。 对象A包含对象B的ArrayList。两者都实现Parcelable。 在A类中写入B对象的列表:

 @Override public void writeToParcel(Parcel dest, int flags) { ... dest.writeList(getMyArrayList()); } 

阅读Aclass的名单:

 public ObjectA(Parcel source) { ... myArrayList= new ArrayList<B>(); source.readList(myArrayList, B.class.getClassLoader()); } 

谢谢!

而不是使用writeParcelable和readParcelable直接使用writeToParcel和createFromParcel。 所以更好的代码是:

 @Override public void writeToParcel(Parcel dest, int flags) { location.writeToParcel(dest, flags); dest.writeLong(start); dest.writeLong(end ); } public static final Parcelable.Creator<LayoverType> CREATOR = new Parcelable.Creator<LayoverType>() { public LayoverType createFromParcel(Parcel in) { return new LayoverType(in); } public LayoverType[] newArray(int size) { return new LayoverType[size]; } }; private LayoverType(Parcel dest) { location = LocationType.CREATOR.createFromParcel(dest); start = dest.readLong(); end = dest.readLong(); } 

那么我有同样的问题,并以一个非常愚蠢的方式解决它,我不知道它是否称为一个解决scheme。

让我们说你有这个类,你想传递给另一个活动

 public class Person implements Parcelable,Serializable{ public String Name; public int Age; @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); dest.writeInt(age); } public SeriesInfo(Parcel in) { age= in.readInt(); //her was my problem as I have put age befor name //while in the writeToParcel function I have defined //dest.writeInt(age) after in.readString();???!!!! name= in.readString(); } } 

多数民众赞成在当我改变:

 dest.writeString(name); dest.writeInt(age); 

 dest.writeInt(age); dest.writeString(name); 

问题解决了!!!!!

如果您有一个具有List对象types属性的对象,则应在读取属性时传递类加载器,例如:

 public class Mall implements Parcelable { public List<Outstanding> getOutstanding() { return outstanding; } public void setOutstanding(List<Outstanding> outstanding) { this.outstanding = outstanding; } protected Mall(Parcel in) { outstanding = new ArrayList<Outstanding>(); //this is the key, pass the class loader in.readList(outstanding, Outstanding.class.getClassLoader()); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeList(outstanding); } public static final Parcelable.Creator<Mall> CREATOR = new Parcelable.Creator<Mall>() { public Mall createFromParcel(Parcel in) { return new Mall(in); } public Mall[] newArray(int size) { return new Mall[size]; } }; } 

注意:类Outstanding实现Parceable接口是重要的。