Container for a message (data and object references) that can
be sent through an IBinder. A Parcel can contain both flattened data
that will be unflattened on the other side of the IPC (using the various
methods here for writing specific types, or the general
Parcelable interface), and
references to live
IBinder objects that will result in the other side receiving a proxy
IBinder
connected with the original IBinder in the Parcel.
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.
The bulk of the Parcel API revolves around reading and writing data of various types. There are
six major classes of such functions available.
Primitives
The most basic data functions are for writing and reading primitive data types:
#writeByte,
#readByte,
#writeDouble,
#readDouble,
#writeFloat,
#readFloat,
#writeInt,
#readInt,
#writeLong,
#readLong,
#writeString,
#readString. Most other data operations are
built on top of these. The given data is written and read using the endianess of the host CPU.
Primitive Arrays
There are a variety of methods for reading and writing raw arrays of primitive objects, which
generally result in writing a 4-byte length followed by the primitive data items. The methods for
reading can either read the data into an existing array, or create and return a new array. These
available types are:
-
#writeBooleanArray(boolean[]),
#readBooleanArray(boolean[]),
#createBooleanArray()
-
#writeByteArray(byte[]),
#writeByteArray(byte[],int,int),
#readByteArray(byte[]),
#createByteArray()
-
#writeCharArray(char[]),
#readCharArray(char[]),
#createCharArray()
-
#writeDoubleArray(double[]),
#readDoubleArray(double[]),
#createDoubleArray()
-
#writeFloatArray(float[]),
#readFloatArray(float[]),
#createFloatArray()
-
#writeIntArray(int[]),
#readIntArray(int[]),
#createIntArray()
-
#writeLongArray(long[]),
#readLongArray(long[]),
#createLongArray()
-
#writeStringArray(String[]),
#readStringArray(String[]),
#createStringArray().
-
#writeSparseBooleanArray(SparseBooleanArray),
#readSparseBooleanArray().
Parcelables
The
Parcelable protocol provides an extremely efficient (but low-level) protocol for
objects to write and read themselves from Parcels. You can use the direct methods
#writeParcelable(Parcelable,int) and
#readParcelable(ClassLoader) or
#writeParcelableArray and
#readParcelableArray(ClassLoader) to write or read.
These methods write both the class type and its data to the Parcel, allowing that class to be
reconstructed from the appropriate class loader when later reading.
There are also some methods that provide a more efficient way to work with Parcelables:
#writeTypedArray,
#writeTypedList(List),
#readTypedArray and
#readTypedList. These methods do not write the class information of the original object:
instead, the caller of the read function must know what type to expect and pass in the
appropriate
Parcelable.Creator instead to properly construct the new
object and read its data. (To more efficient write and read a single Parceable object, you can
directly call
Parcelable#writeToParcel and
Parcelable.Creator#createFromParcel yourself.)
Bundles
A special type-safe container, called
Bundle, is available for key/value maps of
heterogeneous values. This has many optimizations for improved performance when reading and
writing data, and its type-safe API avoids difficult to debug type errors when finally
marshalling the data contents into a Parcel. The methods to use are
#writeBundle(Bundle),
#readBundle(), and
#readBundle(ClassLoader).
Active Objects
An unusual feature of Parcel is the ability to read and write active objects. For these objects
the actual contents of the object is not written, rather a special token referencing the object
is written. When reading the object back from the Parcel, you do not get a new instance of the
object, but rather a handle that operates on the exact same object that was originally written.
There are two forms of active objects available.
Binder objects are a core facility of Android's general cross-process communication
system. The
IBinder interface describes an abstract protocol with a Binder object. Any
such interface can be written in to a Parcel, and upon reading you will receive either the
original object implementing that interface or a special proxy implementation that communicates
calls back to the original object. The methods to use are
#writeStrongBinder(IBinder),
#writeStrongInterface(IInterface),
#readStrongBinder(),
#writeBinderArray(IBinder[]),
#readBinderArray(IBinder[]),
#createBinderArray(),
#writeBinderList(List),
#readBinderList(List),
#createBinderArrayList().
FileDescriptor objects, representing raw Linux file descriptor identifiers, can be written and
ParcelFileDescriptor objects returned to operate on the original file descriptor. The
returned file descriptor is a dup of the original file descriptor: the object and fd is
different, but operating on the same underlying file stream, with the same position, etc. The
methods to use are
#writeFileDescriptor(FileDescriptor),
#readFileDescriptor().
Untyped Containers
A final class of methods are for writing and reading standard Java containers of arbitrary types.
These all revolve around the
#writeValue(Object) and
#readValue(ClassLoader)methods which define the types of objects allowed. The container methods are
#writeArray(Object[]),
#readArray(ClassLoader),
#writeList(List),
#readList(List,ClassLoader),
#readArrayList(ClassLoader),
#writeMap(Map),
#readMap(Map,ClassLoader),
#writeSparseArray(SparseArray),
#readSparseArray(ClassLoader).