2013-08-01 11 views
35

Voglio marshall e unmarshall una classe che implementa Parcelable in/da un array di byte. Sono ben consapevole del fatto che la rappresentazione Parcelable non è stabile e quindi non è pensata per l'archiviazione a lungo termine delle istanze. Ma ho un caso d'uso in cui ho bisogno di serializzare un oggetto e non è un fermo di scena se l'unmarshalling fallisce a causa di una modifica interna di Android. Anche la classe sta già implementando l'interfaccia Parcelable.Come eseguire il marshall e l'unmarshall Parcelable su un array di byte con l'aiuto di Parcel?

Data una classe MyClass implements Parcelable, come è possibile (ab) utilizzare l'interfaccia Parcelable per marshalling/unmarshalling?

risposta

97

Innanzitutto creare una classe di supporto ParcelableUtil.java:

public class ParcelableUtil {  
    public static byte[] marshall(Parcelable parceable) { 
     Parcel parcel = Parcel.obtain(); 
     parceable.writeToParcel(parcel, 0); 
     byte[] bytes = parcel.marshall(); 
     parcel.recycle(); 
     return bytes; 
    } 

    public static Parcel unmarshall(byte[] bytes) { 
     Parcel parcel = Parcel.obtain(); 
     parcel.unmarshall(bytes, 0, bytes.length); 
     parcel.setDataPosition(0); // This is extremely important! 
     return parcel; 
    } 

    public static <T> T unmarshall(byte[] bytes, Parcelable.Creator<T> creator) { 
     Parcel parcel = unmarshall(bytes); 
     T result = creator.createFromParcel(parcel); 
     parcel.recycle(); 
     return result; 
    } 
} 

Con l'aiuto della classe util sopra, è possibile Marshall/istanze unmarshall della vostra classe MyClass implements Parcelable in questo modo:

unmarshalling (con CREATOR)

byte[] bytes = … 
MyClass myclass = ParcelableUtil.unmarshall(bytes, MyClass.CREATOR); 

deserializzazione (senza CREATOR)

byte[] bytes = … 
Parcel parcel = ParcelableUtil.unmarshall(bytes); 
MyClass myclass = new MyClass(parcel); // Or MyClass.CREATOR.createFromParcel(parcel). 

Marshalling

MyClass myclass = … 
byte[] bytes = ParcelableUtil.marshall(myclass); 
+4

'parcel.setDataPosition (0); // questo è estremamente importante! 'questo mi aiuta molto. la mancanza del documento Android di questo, fa davvero schifo. –

+0

Grazie mille per questo suggerimento. Implementare Parcelable (che è estremamente soggetto a errori e otterrete eccezioni runtime senza significato e clienti arrabbiati se non fatto bene) è un tale PITA - sto evitando Parcelables nel mio codice del tutto e sto usando Serializables. Sui telefoni moderni, il colpo di velocità è appena percettibile. –

+1

L'unico problema con questo approccio, tuttavia, è che l'unmarshalling di una sottoclasse di classi che implementa Parcelable non sarà così semplice. Dovrai passare informazioni extra da cui puoi giudicare il Creatore corretto da usare. – bosphere

-3
public static byte[] pack(Parcelable parcelable) { 
    Parcel parcel = Parcel.obtain(); 
    parcelable.writeToParcel(parcel, 0); 
    byte[] bytes = parcel.marshall(); 
    parcel.recycle(); 
    return bytes; 
} 

public static <T> T unpack(byte[] bytes, Parcelable.Creator<T> creator) { 
    Parcel parcel = Parcel.obtain(); 
    parcel.unmarshall(bytes, 0, bytes.length); 
    parcel.setDataPosition(0); 
    return creator.createFromParcel(parcel); 
} 

MyObject myObject = unpack(new byte[]{/* bytes */}, MyObject.CREATOR); 
+2

Fornire una breve spiegazione del codice che è stato postato in modo che sia più semplice da comprendere per OP. – Jatin

Problemi correlati