Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Parcel in Android?

Tags:

android

parcel

I'm trying to use Parcel to write and then read back a Parcelable. For some reason, when I read the object back from the file, it's coming back as null.

public void testFoo() {     final Foo orig = new Foo("blah blah");      // Wrote orig to a parcel and then byte array     final Parcel p1 = Parcel.obtain();     p1.writeValue(orig);     final byte[] bytes = p1.marshall();       // Check to make sure that the byte array seems to contain a Parcelable     assertEquals(4, bytes[0]); // Parcel.VAL_PARCELABLE       // Unmarshall a Foo from that byte array     final Parcel p2 = Parcel.obtain();     p2.unmarshall(bytes, 0, bytes.length);     final Foo result = (Foo) p2.readValue(Foo.class.getClassLoader());       assertNotNull(result); // FAIL     assertEquals( orig.str, result.str ); }   protected static class Foo implements Parcelable {     protected static final Parcelable.Creator<Foo> CREATOR = new Parcelable.Creator<Foo>() {         public Foo createFromParcel(Parcel source) {             final Foo f = new Foo();             f.str = (String) source.readValue(Foo.class.getClassLoader());             return f;         }          public Foo[] newArray(int size) {             throw new UnsupportedOperationException();         }      };       public String str;      public Foo() {     }      public Foo( String s ) {         str = s;     }      public int describeContents() {         return 0;     }      public void writeToParcel(Parcel dest, int ignored) {         dest.writeValue(str);     }   } 

What am I missing?

UPDATE: To simplify the test I've removed the reading and writing of files in my original example.

like image 696
emmby Avatar asked Oct 26 '09 18:10

emmby


People also ask

What is Android parcel?

A Parcelable is the Android implementation of the Java Serializable. It assumes a certain structure and way of processing it. This way a Parcelable can be processed relatively fast, compared to the standard Java serialization.

Why do we use Parcelable in Android?

Parcelable and Bundle objects are intended to be used across process boundaries such as with IPC/Binder transactions, between activities with intents, and to store transient state across configuration changes.

How do you create a parcel object?

Create Parcelable class without plugin in Android Studioimplements Parcelable in your class and then put cursor on "implements Parcelable" and hit Alt+Enter and select Add Parcelable implementation (see image). that's it.


2 Answers

Ah, I finally found the problem. There were two in fact.

  1. CREATOR must be public, not protected. But more importantly,
  2. You must call setDataPosition(0) after unmarshalling your data.

Here is the revised, working code:

public void testFoo() {     final Foo orig = new Foo("blah blah");     final Parcel p1 = Parcel.obtain();     final Parcel p2 = Parcel.obtain();     final byte[] bytes;     final Foo result;      try {         p1.writeValue(orig);         bytes = p1.marshall();          // Check to make sure that the byte stream seems to contain a Parcelable         assertEquals(4, bytes[0]); // Parcel.VAL_PARCELABLE          p2.unmarshall(bytes, 0, bytes.length);         p2.setDataPosition(0);         result = (Foo) p2.readValue(Foo.class.getClassLoader());      } finally {         p1.recycle();         p2.recycle();     }       assertNotNull(result);     assertEquals( orig.str, result.str );  }  protected static class Foo implements Parcelable {     public static final Parcelable.Creator<Foo> CREATOR = new Parcelable.Creator<Foo>() {         public Foo createFromParcel(Parcel source) {             final Foo f = new Foo();             f.str = (String) source.readValue(Foo.class.getClassLoader());             return f;         }          public Foo[] newArray(int size) {             throw new UnsupportedOperationException();         }      };       public String str;      public Foo() {     }      public Foo( String s ) {         str = s;     }      public int describeContents() {         return 0;     }      public void writeToParcel(Parcel dest, int ignored) {         dest.writeValue(str);     }   } 
like image 55
emmby Avatar answered Oct 25 '22 03:10

emmby


Beware! Dont use Parcel for serialization to a file

Parcel is not a general-purpose serialization mechanism. This class (and the corresponding Parcelable API for placing arbitrary objects into a Parcel) is designed as a high-performance IPC transport. As such, it is not appropriate to place any Parcel data in to persistent storage: changes in the underlying implementation of any of the data in the Parcel can render older data unreadable.

from http://developer.android.com/reference/android/os/Parcel.html

like image 44
Carl D'Halluin Avatar answered Oct 25 '22 01:10

Carl D'Halluin