Domanda

Ho un paio di classi che implementano Parcelable e un po ' di queste classi contengono reciprocamente come proprietà. Sto smistamento delle classi in un Parcel per passarli tra le attività. li Marshalling al pacco funziona bene, ma quando provo a unmarshall le ricevo il seguente errore:

...
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 classe LayoverType (dove è mancato):

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();
    }
}

Ecco la classe 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();
    }
}

Aggiorna 2 : Per quanto mi riguarda posso dire che è mancato al seguente pezzo di codice (da del pacchetto sorgente ):

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

Perché non è in grado di trovare la classe? E sia esiste e implementa Parcelable.

È stato utile?

Soluzione

Perché questo non è stato risposto in "risposta" ma nel commento che pubblicherà una risposta: Come @ Max-Gontar ha sottolineato che si dovrebbe usare LocationType.class.getClassLoader () per ottenere la corretta ClassLoader e di sbarazzarsi di eccezione ClassNotFound, cioè:.

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

Altri suggerimenti

Ho avuto lo stesso problema con la seguente configurazione:. Qualche gestore crea un messaggio e invia il suo corso di un messaggero per un servizio remoto

Il messaggio contiene un bundle in cui ho messo il mio discendente Parcelable:

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

messenger.send(msg);

Ho avuto la stessa eccezione quando il servizio remoto ha tentato di unparcel. Nel mio caso, ho supervisionato che il servizio remoto è infatti un processo di sistema operativo separato. Pertanto, ho dovuto impostare il programma di caricamento classe corrente per essere utilizzato dal processo unparcelling sul lato del servizio:

final Bundle bundle = msg.getData();
bundle.setClassLoader(getClassLoader());

DownloadFileURLItem urlItem = (DownloadFileURLItem)
bundle.getParcelable("DOWNLOADFILEURLITEM");

Bundle.setClassLoader imposta il classloader che viene utilizzato per caricare le classi Parcelable appropriate. In un servizio remoto, è necessario reimpostare alla classe caricatore di corrente.

Ho trovato il problema era che non passavo il mio applicazioni ClassLoader alla funzione unmarshalling:

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

Piuttosto che:

in.readParceleable(null); 

o

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

Basta aggiungere i miei 2 centesimi qui, perché ho perso più di mezza giornata graffiare la mia testa su questo. Si potrebbe ottenere questo errore se non si mettono i metodi scrive e legge metodi nella esattamente lo stesso ordine. Ad esempio, la seguente sarebbe sbagliato:

 @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();
    }

Tra l'altro l'autore ha fatto questo in modo corretto ma potrebbe aiutare qualcuno un giorno.

Io non sono molto familiare con Parcelable ma se si tratta di qualcosa di simile serializzazione ogni chiamata di scrivere un oggetto che implementa l'interfaccia causerà una chiamata ricorsiva a writeToParcel (). Pertanto, se qualcosa lungo la stack di chiamate non riesce o scrive un valore nullo della classe che ha avviato la chiamata non può essere costruito in modo corretto.

Prova: Tracciare la writeToParcel stack di chiamate () attraverso tutte le classi da prima chiamata a writeToParcel () e verificare che tutti i valori sono sempre inviati correttamente.

Ho ClassNotFoundException troppo e il distacco mia soluzione bc le risposte qui mi hanno portato nella giusta direzione. Il mio scenario è che ho nidificati oggetti Parcelable. L'oggetto A contiene un ArrayList di B. Sia implementare Parcelable di oggetto. Scrivendo l'elenco dei del B Oggetto in classe A:

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

}

La lettura della lista in classe A:

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

Grazie!

Invece di usare writeParcelable e readParcelable usano writeToParcel e createFromParcel direttamente. Quindi il codice migliore è:

@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();
}

Beh, ho avuto lo stesso problema e risolverlo in un modo molto stupido che non so se la sua chiamata una soluzione a tutti.

Diciamo che avere questa classe si desidera passare ad un'altra attività

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();

}
}

Ecco fatto quando ho cambiato il:

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

a

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

Il problema è stato risolto ??? !!!!

Se si dispone di un oggetto con una proprietà di tipo di lista oggetti si dovrebbe passare il caricatore di classe quando si legge la proprietà, ad esempio:

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: E 'importante che la classe eccezionale implementa l'interfaccia Parceable

.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top