java - online - putparcelable android
Problema que deshace parcelas (9)
Tengo algunas clases que implementan Parcelable y algunas de estas clases se contienen entre sí como propiedades. Organizo las clases en una Parcel para pasarlas entre actividades. Al ordenarlos para el paquete funciona bien, pero cuando intento deshacerlos obtengo el siguiente error:
...
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)
...
La clase LayoverType
(donde está fallando):
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();
}
}
Aquí está la clase 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();
}
}
Actualización 2 : Por lo que puedo decir, está fallando en el siguiente bit de código (de la fuente de Parcel ):
Class c = loader == null ? Class.forName(name) : Class.forName(name, true, loader);
¿Por qué no puede encontrar la clase? Existe e implementa Parcelable
.
Bueno, tuve el mismo problema y lo resolví de una manera muy tonta que no sé si se llama una solución.
digamos que tienes esta clase que quieres pasar a otra actividad
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();
}
}
Eso es cuando cambié el:
dest.writeString(name);
dest.writeInt(age);
a
dest.writeInt(age);
dest.writeString(name);
¡¡¡¡¿¿¿El problema fue resuelto???!!!!
Debido a que esto no fue respondido en "respuesta", pero en el comentario publicaré una respuesta: como @ Max-Gontar señaló que debe usar LocationType.class.getClassLoader () para obtener el ClassLoader correcto y deshacerse de la excepción ClassNotFound, es decir:
in.readParceleable(LocationType.class.getClassLoader());
En lugar de utilizar writeParcelable y readParcelable, use writeToParcel y createFromParcel directamente. Entonces, el mejor código es:
@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();
}
Encontré que el problema era que no estaba pasando mis aplicaciones ClassLoader a la función de eliminación de clasificaciones:
in.readParceleable(getContext().getClassLoader());
Más bien que:
in.readParceleable(null);
O
in.readParceleable(MyClass.class.getClassLoader());
No estoy muy familiarizado con Parcelable, pero si se trata de Serialización, cada llamada para escribir un objeto que implemente la interfaz provocará una llamada recursiva a writeToParcel (). Por lo tanto, si algo a lo largo de la pila de llamadas falla o escribe un valor nulo, la clase que inició la llamada puede no estar construida correctamente.
Pruebe: trace la pila de llamadas writeToParcel () a través de todas las clases desde la primera llamada a writeToParcel () y verifique que todos los valores se envían correctamente.
Obtuve ClassNotFoundException también y publicar mi solución por aquí las respuestas me condujo a la dirección correcta. Mi escenario es que he anidado objetos que se pueden parcelar. El objeto A contiene una ArrayList de Object''s B. Ambas implementan Parcelable. Escribir la lista de objetos B en la clase A:
@Override
public void writeToParcel(Parcel dest, int flags) {
...
dest.writeList(getMyArrayList());
}
Leyendo la lista en la clase A:
public ObjectA(Parcel source) {
...
myArrayList= new ArrayList<B>();
source.readList(myArrayList, B.class.getClassLoader());
}
¡Gracias!
Si tiene un objeto con una propiedad del tipo de objetos List, debe pasar el cargador de clases cuando lea la propiedad, por ejemplo:
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];
}
};
}
Nota: Es importante que la clase Sobresaliente implemente la interfaz Parceable.
Solo agregué mis 2 centavos aquí, porque perdí más de medio día rascándome la cabeza con esto. Es posible que obtenga este error si no coloca los métodos de escritura y lee los métodos en el mismo orden. Por ejemplo, lo siguiente sería incorrecto:
@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();
}
Por cierto, el autor hizo esto correctamente, pero podría ayudar a alguien algún día.
Tuve el mismo problema con la siguiente configuración: algún controlador crea un mensaje y lo envía a través de un Messenger a un servicio remoto.
el mensaje contiene un paquete donde pongo mi descendiente parcelable:
final Message msg = Message.obtain(null, 0);
msg.getData().putParcelable("DOWNLOADFILEURLITEM", downloadFileURLItem);
messenger.send(msg);
Tuve la misma excepción cuando el servicio remoto intentó desconectarse. En mi caso, había supervisado que el servicio remoto es de hecho un proceso de sistema operativo independiente. Por lo tanto, tuve que configurar el cargador de clases actual para ser utilizado por el proceso unparcelling en el lado del servicio:
final Bundle bundle = msg.getData();
bundle.setClassLoader(getClassLoader());
DownloadFileURLItem urlItem = (DownloadFileURLItem)
bundle.getParcelable("DOWNLOADFILEURLITEM");
Bundle.setClassLoader establece el cargador de clases que se usa para cargar las clases Parcelable apropiadas. En un servicio remoto, debe restablecerlo al cargador de clases actual.