问题解组的问题
我有几个类实现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接口是重要的。