Android 序列化比对

来源:互联网 发布:淘宝买的手机怎么保修 编辑:程序博客网 时间:2024/06/02 16:10

Android 序列化比对


在Android中使用序列化,无非两种途经: ParcelableSerializable

两者区别

  • Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。
  • Parcelable的设计初衷是因为Serializable效率过慢,为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable是通过IBinder通信的消息的载体。如果想进一步了解进程间通信AIDL方式可以看博文:Android 进程间通信IPC_AIDL
  • Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如activity间传输数据
  • Serializable可将数据持久化方便保存,所以在需要保存或网络传输数据时选择Serializable,因为android不同版本Parcelable可能不同,所以不推荐使用Parcelable进行数据持久化

Serializable

public class SerializableDeveloper implements Serializable    String name;    int yearsOfExperience;    List<Skill> skillSet;    float favoriteFloat;    static class Skill implements Serializable {        String name;        boolean programmingRelated;    }}

serializable的迷人之处在于你只需要对某个类以及它的属性实现Serializable 接口即可。Serializable 接口是一种标识接口(marker interface),这意味着无需实现方法,Java便会对这个对象进行高效的序列化操作。
这种方法的缺点是使用了反射,序列化的过程较慢。这种机制会在序列化的时候创建许多的临时对象,容易触发垃圾回收。

Parcelable

class 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;        }    }}

根据 google 工程师的说法,这些代码将会运行地特别快。原因之一就是我们已经清楚地知道了序列化的过程,而不需要使用反射来推断。同时为了更快地进行序列化,对象的代码也需要高度优化。
因此,很明显实现Parcelable并不容易。实现Parcelable接口需要写大量的模板代码,这使得对象代码变得难以阅读和维护。

性能测试

通过将一个对象放到一个bundle里面然后调用Bundle#writeToParcel(Parcel, int)方法来模拟传递对象给一个activity的过程,然后再把这个对象取出来,在一个循环里面运行1000 次。

此处输入图片的描述

小结

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

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

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

另外有一种说法是:在Activity之间传递数据使用Serializable在某种情况下会失败,这样的案例尚未遇到过。(个人猜测:难道是持久化数据需要写入扩展SD卡,如果一旦出现写入或者读取失败,那么传输就会失败)

本文翻译和整理自:http://www.developerphil.com/parcelable-vs-serializable/

0 0
原创粉丝点击