个人学习笔记,才疏学浅,如有疏漏,还望斧正。
之前在做项目的时候,遇到如何将数据传输跨activity传输的问题。当时上网百度了一下,发现传输自定义对象可以用序列化。而序列化有两种,一种是java的Serializable,一种是android推荐的Parcelable。
当时看见完Serializable的实现,只需要在自定义对象后面继承Serializable,然后用就完事。
public class Person implements Serializable{
//省略
}
再看Parceable,除了继承以外,还要重写N个方法,当时我就惊了,怎么会有人放着简单的方法不去用?有这时间搓两把炉石不香吗?这是选择题吗?这是送分题啊兄弟。
于是懒癌晚期 追求开发速度的我果断选择了Serializable。
但毕竟开发android的大神毕竟不是我这种菜逼,,既然有两种不同的方法,肯定另一种有可取之处,于是现在回来补当初的坑。
目录
(1)public int describeContents()
(2)public void writeToParcel()
(3)静态的Parcelable.Creator接口,有两个方法。
一、Parcelable的简介
1、什么是序列化?
因为android进程之间是隔离的,就好比联盟和部落之间不能直接交易,所以要靠加基森拍卖行才能交付数据。对象也是如此,无法直接传递给activity或者service,要借助intent或者bundle这两种方式。而这两个类打开源码我们都可以看见它们实际上都继承了parceable。
public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
//省略
}
public class Intent implements Parcelable, Cloneable {
//省略
}
至于啥是Cloneable ,肯定有兄弟会好奇,但是咱们懒得等有空再看。
所以所谓的序列化呢,就是把对象转化成可以跨进程传输的二进制流的形式,然后等传到了以后再反序列化恢复成本来的亚子。
2、和Serializable的区别?
有失必有得,比较Serializable,它的效率是十倍以上【据说】。
然后使用原则也有区别。这里我就直接抄的别人的。
1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。
2)Serializable在序列化的时候会产生大量的临时变量和频繁的I/O操作,从而引起频繁的GC。【所以这就是效率低的原因吗?(小声bb)】
3)Parcelable不能使用在要将数据存储在磁盘上的情况。因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。【看不懂】
二、Parcelable的使用
至于怎么用,源码里早就安排的明明白白。
/**
*源码示例
* <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 {
//...
}
大概就是自定义的数据类对象,继承Parcelable后,实现两个方法和一个接口里的两个方法。看起来很唬人,其实都是纸老虎。真正需要稍微写一下的就一个方法。
以下介绍这些方法
(1)public int describeContents()
/**
* 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();
有点看不懂,大概就是描述这个对象的类型。大部分情况返回0就行了。如
@Override
public int describeContents() {
return 0;
}
(2)public void writeToParcel()
/**
* 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);
将要转化的对象转化成parcel类型,第一个参数是数据保存的parcel,第二个参数是标志位,代表是否需要将对象作为返回值。真正需要自己写的基本上都在这里。如
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(music_name);//好像要按照顺序写,否则会出错
dest.writeString(music_author);
dest.writeInt(play_time);
}
(3)静态的Parcelable.Creator接口,有两个方法。
-
createFromParcel(Parcel in)
/**
* 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);
创建一个music的对象,并通过之前writeToParce()已经赋好值的parcel类实例化这个music对象。
-
newArray(int size)
/**
* 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);
返回一个music类型的数组,大小为size 。如
@Override
public Music createFromParcel(Parcel in) {
return new Music(in);
}
@Override
public Music[] newArray(int size) {
return new Music[size];
}