无论是android中还是Java中,远程传递数据都是需要序列化的,android中不同组件之间传递数据也是需要序列化的。
1、序列化和反序列化
序列化和反序列化是一个过程,这个过程其实就是我们给数据加一层标识,告诉虚拟机序列化的时候该怎么给数据加壳,反序列化的时候该怎么将数据的壳去掉,取出其中的数据。
实现序列化的方式有两种:Serializable接口和Parcelable接口
2、Serializable接口
Java提供的接口,主要用于文件读写和网络传输数据,也可以用于android组件之间传递数据,只是因为Serializable接口操作数据时候,序列化和反序列化时候,会产生大量的变量,也会有频繁的IO操作,开销大,导致在组件之间传递数据时候效率低,所以不建议在android组件之间传递数据。
/**
*
* Classes that require special handling during the serialization and
* deserialization process must implement special methods with these exact
* signatures:
*
* <PRE>
* private void writeObject(java.io.ObjectOutputStream out)
* throws IOException
* private void readObject(java.io.ObjectInputStream in)
* throws IOException, ClassNotFoundException;
* private void readObjectNoData()
* throws ObjectStreamException;
* </PRE>
* <PRE>
* ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
* </PRE>
* @author unascribed
* @see java.io.ObjectOutputStream
* @see java.io.ObjectInputStream
* @see java.io.ObjectOutput
* @see java.io.ObjectInput
* @see java.io.Externalizable
* @since JDK1.1
*/
public interface Serializable {
}
上面就是Serializable接口在源码中的定义,可以看出来内部就是空的,没有任何方法要去实现,上面注释中提醒我们使用的时候都是要在IO流中使用,并且最好设置serialVersionUID,作为唯一的标识。其实实现过程都是由jdk虚拟机去实现了,我们无需操心具体的实现细节,使用简单方便。
3、Parcelable接口
android提供的接口,主要用于不同组件之间传递数据,因为内部实现靠自定义操作,所以相对于Serializable接口来说,实现比较麻烦,但是给了开发人员高度的自由度,序列化和反序列化时候,不会产生大量的变量,也不会有频繁的IO操作,所以序列化和反序列化时候开销小,效率高。
特别要注意的是:不能用来进行文件操作,否则会报异常。
/**
* Interface for classes whose instances can be written to
* and restored from a {@link Parcel}. Classes implementing the Parcelable
* interface must also have a non-null static field called <code>CREATOR</code>
* of a type that implements the {@link Parcelable.Creator} interface.
*
* <p>A typical implementation of Parcelable is:</p>
*
* <pre>
* public class MyParcelable implements Parcelable {
* private int mData;
*
* public int describeContents() {
* return 0;
* }
*
* public void writeToParcel(Parcel out, int flags) {
* out.writeInt(mData);
* }
*
* public static final Parcelable.Creator<MyParcelable> CREATOR
* = new Parcelable.Creator<MyParcelable>() {
* public MyParcelable createFromParcel(Parcel in) {
* return new MyParcelable(in);
* }
*
* public MyParcelable[] newArray(int size) {
* return new MyParcelable[size];
* }
* };
*
* private MyParcelable(Parcel in) {
* mData = in.readInt();
* }
* }</pre>
*/
public interface Parcelable {
/** @hide */
@IntDef(flag = true, prefix = { "PARCELABLE_" }, value = {
PARCELABLE_WRITE_RETURN_VALUE,
PARCELABLE_ELIDE_DUPLICATES,
})
@Retention(RetentionPolicy.SOURCE)
public @interface WriteFlags {}
public static final int PARCELABLE_WRITE_RETURN_VALUE = 0x0001;
public static final int PARCELABLE_ELIDE_DUPLICATES = 0x0002;
/*
* Bit masks for use with {@link #describeContents}: each bit represents a kind of object considered to have potential special significance when marshalled.
*/
/** @hide */
@IntDef(flag = true, prefix = { "CONTENTS_" }, value = {
CONTENTS_FILE_DESCRIPTOR,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ContentsFlags {}
/**
* Descriptor bit used with {@link #describeContents()}: indicates that
* the Parcelable object's flattened representation includes a file descriptor.
*
* @see #describeContents()
*/
public static final int CONTENTS_FILE_DESCRIPTOR = 0x0001;
/**
* Describe the kinds of special objects contained in this Parcelable
* instance's marshaled representation. For example, if the object will
* include a file descriptor in the output of {@link #writeToParcel(Parcel, int)},
* the return value of this method must include the
* {@link #CONTENTS_FILE_DESCRIPTOR} bit.
*
* @return a bitmask indicating the set of special object types marshaled
* by this Parcelable object instance.
*/
public @ContentsFlags int describeContents();
/**
* Flatten this object in to a Parcel.
*
* @param dest The Parcel in which the object should be written.
* @param flags Additional flags about how the object should be written.
* May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
*/
public void writeToParcel(Parcel dest, @WriteFlags int flags);
/**
* Interface that must be implemented and provided as a public CREATOR
* field that generates instances of your Parcelable class from a Parcel.
*/
public interface Creator<T> {
/**
* Create a new instance of the Parcelable class, instantiating it
* from the given Parcel whose data had previously been written by
* {@link Parcelable#writeToParcel Parcelable.writeToParcel()}.
*
* @param source The Parcel to read the object's data from.
* @return Returns a new instance of the Parcelable class.
*/
public T createFromParcel(Parcel source);
/**
* Create a new array of the Parcelable class.
*
* @param size Size of the array.
* @return Returns an array of the Parcelable class, with every entry
* initialized to null.
*/
public T[] newArray(int size);
}
/**
* Specialization of {@link Creator} that allows you to receive the
* ClassLoader the object is being created in.
*/
public interface ClassLoaderCreator<T> extends Creator<T> {
/**
* Create a new instance of the Parcelable class, instantiating it
* from the given Parcel whose data had previously been written by
* {@link Parcelable#writeToParcel Parcelable.writeToParcel()} and
* using the given ClassLoader.
*
* @param source The Parcel to read the object's data from.
* @param loader The ClassLoader that this object is being created in.
* @return Returns a new instance of the Parcelable class.
*/
public T createFromParcel(Parcel source, ClassLoader loader);
}
}
由此可以看出,实现Parcelable接口,内部过程都是需要自己实现的,自由度更高,但是也增加开发成本。