2013-08-01 8 views
35

Ich möchte Marshall und Marshall eine Klasse, die Parcelable zu/von einem Byte-Array implementiert Marshall und Unmarshall. Ich bin mir der Tatsache bewusst, dass die Parcelable-Darstellung nicht stabil ist und daher nicht für die langfristige Speicherung von Instanzen gedacht ist. Aber ich habe einen Anwendungsfall, in dem ich ein Objekt serialisieren muss und es ist kein Showstopper, wenn das Entpacken wegen einer internen Android-Änderung fehlschlägt. Außerdem implementiert die Klasse bereits die Schnittstelle Parcelable.Wie man ein Parcelable zu einem Byte-Array mit Hilfe von Parcel marshall und unmarshall?

Wie lautet die Klasse MyClass implements Parcelable? Wie kann ich die Schnittstelle Parcelable zum Marshalling/Unmarshalling verwenden?

Antwort

97

Zuerst eine Hilfsklasse erstellen 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; 
    } 
} 

Mit Hilfe der util Klasse oben, können Sie marshall/unmarshall Instanzen Ihrer Klasse MyClass implements Parcelable wie so:

Unmarshalling (mit CREATOR)

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

Unmarshalling (ohne CREATOR)

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

Rangierung

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

'parcel.setDataPosition (0); // das ist extrem wichtig! 'das hilft mir sehr. Das Fehlen von Android-Dokument davon ist wirklich scheiße. –

+0

Vielen Dank für diesen Tipp. Das Implementieren von Parcelable (das extrem fehleranfällig ist und Sie sinnlose Laufzeitausnahmen und verärgerte Kunden erhalten, wenn es nicht richtig gemacht wird) ist eine solche PITA - ich vermeide Parcelables in meinem Code insgesamt und verwende Serialisables. Auf modernen Telefonen ist der Geschwindigkeitshit kaum wahrnehmbar. –

+1

Das einzige Problem bei diesem Ansatz besteht jedoch darin, dass das Unmarshalling einer Unterklasse der Klasse, die Parcelable implementiert, nicht so einfach ist. Du musst zusätzliche Informationen weitergeben, anhand derer du den richtigen Schöpfer beurteilen kannst. – 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

Bitte geben Sie eine kurze Erklärung des Codes, den Sie gebucht, so dass es für OP leichter zu verstehen ist. – Jatin