Android中的Serializable和Parcelable

来源:互联网 发布:excel数据库设计 编辑:程序博客网 时间:2024/06/11 02:30

序列化原因

Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。需要在多个部件(Activity或Service)之间通过Intent传递一些数据,简单类型(如:数字、字符串)的可以直接放入Intent。复杂类型必须实现序列化接口。而Android的Parcelable的设计初衷是因为Serializable效率过慢,为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable是通过IBinder通信的消息的载体。从设计上我们就可以看出优劣了。

  1. 永久性保存对象,保存对象的字节序列到本地文件中;
  2. 通过序列化对象在网络中传递对象;
  3. 通过序列化在进程间传递对象。

至于选取哪种可参考下面的原则

1.在使用内存的时候,Parcelable 类比Serializable性能高,所以推荐使用Parcelable类
2.Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
3.Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点, 也不提倡用,但在这种情况下,还是建议你用Serializable 。

两种方式实现

一:Serializable,要传递的类实现Serializable接口传递对象;
二:Parcelable,要传递的类实现Parcelable接口传递对象。

Serializable, 简单易用(Java自带):
Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。

serializable的迷人之处在于你只需要对某个类以及它的属性实现Serializable 接口即可。Serializable 接口是一种标识接口(marker interface),这意味着无需实现方法,Java便会对这个对象进行高效的序列化操作。

这种方法的缺点是使用了反射,序列化的过程较慢。这种机制会在序列化的时候创建许多的临时对象,容易触发垃圾回收。

Serializable序列化不保存静态变量,可以使用Transient关键字对部分字段不进行序列化,也可以覆盖writeObject、readObject方法以实现序列化过程自定义。

// access modifiers, accessors and constructors omitted for brevitypublic class SerializableDeveloper implements Serializable    String name;    int yearsOfExperience;    List<Skill> skillSet;    float favoriteFloat;    static class Skill implements Serializable {        String name;        boolean programmingRelated;    }}

下来一个示例展示

// MainActivity中传递Intent open = new Intent(MainActivity.this,SecondActivity.class);Person person = new Person();// Person类是实现了Serializable接口的person.setName("张张");person.setAge(18);Bundle bundle = new Bundle();bundle.putSerializable("bundle_ser",person);open.putExtras(bundle);startActivity(open);// SecondActivity中接收Intent intent = getIntent();// 关键方法:getSerializableExtra ,我们的类是实现了Serializable接口的,所以写这个方法获得对象Person per = (Person)intent.getSerializableExtra("bundle_ser");

Parcelable, 速度至上(Android 专用):
除了Serializable之外,使用Parcelable也可以实现相同的效果,不过不同于将对象进行序列化,Parcelable方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了。

根据 google 工程师的说法,这些代码将会运行地特别快。原因之一就是我们已经清楚地知道了序列化的过程,而不需要使用反射来推断。同时为了更快地进行序列化,对象的代码也需要高度优化。

因此,很明显实现Parcelable并不容易。实现Parcelable接口需要写大量的模板代码,这使得对象代码变得难以阅读和维护。

我们写一个实体类,实现Parcelable接口,马上就被要求

  1. 复写describeContents方法和writeToParcel方法
  2. 实例化静态内部对象CREATOR,实现接口Parcelable.Creator 。

也就是,随便一个类实现了Parcelable接口就一开始就会变成这样子,Parcelable方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了。

// access modifiers, accessors and regular constructors ommited for brevityclass ParcelableDeveloper implements Parcelable {    String name;    int yearsOfExperience;    List<Skill> skillSet;    float favoriteFloat;    ParcelableDeveloper(Parcel in) {        this.name = in.readString();        this.yearsOfExperience = in.readInt();        this.skillSet = new ArrayList<Skill>();        in.readTypedList(skillSet, Skill.CREATOR);        this.favoriteFloat = in.readFloat();    }    void writeToParcel(Parcel dest, int flags) {        dest.writeString(name);        dest.writeInt(yearsOfExperience);        dest.writeTypedList(skillSet);        dest.writeFloat(favoriteFloat);    }    int describeContents() {        return 0;    }    static final Parcelable.Creator<ParcelableDeveloper> CREATOR            = new Parcelable.Creator<ParcelableDeveloper>() {        ParcelableDeveloper createFromParcel(Parcel in) {            return new ParcelableDeveloper(in);        }        ParcelableDeveloper[] newArray(int size) {            return new ParcelableDeveloper[size];        }    };    static class Skill implements Parcelable {        String name;        boolean programmingRelated;        Skill(Parcel in) {            this.name = in.readString();            this.programmingRelated = (in.readInt() == 1);        }        @Override        void writeToParcel(Parcel dest, int flags) {            dest.writeString(name);            dest.writeInt(programmingRelated ? 1 : 0);        }        static final Parcelable.Creator<Skill> CREATOR            = new Parcelable.Creator<Skill>() {            Skill createFromParcel(Parcel in) {                return new Skill(in);            }            Skill[] newArray(int size) {                return new Skill[size];            }        };        @Override        int describeContents() {            return 0;        }    }}

示例演示

// MainActivity发送传递Intent mOpenThird = new Intent(MainActivity.this, ThirdActivity.class);Pen tranPen = new Pen();// Pen类是实现了Parcelable接口的tranPen.setColor("big red");tranPen.setSize(98);mOpenThird.putExtra("parcel_obj",tranPen);startActivity(mTvOpenThird);// ThirdActivity中接收Pen pen = (Pen)getIntent().getParcelableExtra("parcel_obj");

总结

如果你想成为一个优秀的软件工程师,你需要多花点时间来实现 Parcelable ,因为这将会为你对象的序列化过程快10多倍,而且占用较少的资源。

但是大多数情况下, Serializable 的龟速不会太引人注目。你想偷点懒就用它吧,不过要记得serialization是一个比较耗资源的操作,尽量少使用。

如果你想要传递一个包含许多对象的列表,那么整个序列化的过程的时间开销可能会超过一秒,这会让屏幕转向的时候变得很卡顿。

0 0