SerializableParcelable 的简介及区别

Posted Flow_孙权

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SerializableParcelable 的简介及区别相关的知识,希望对你有一定的参考价值。

前言

众所周知,在 android 开发中,我们无法将对象的引用传给 Activity 或者 Fragment,我们需要将对象放到一个Intent或者Bundle里面,然后再进行传递,所以我们就需要用到对象的序列化。将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。Android 中序列化的方式有两种,一种是 Serializable(Java 自带),一种是 Parcelable(Android 专用)。

Serializable

Serializable 是 Java 提供的一个序列化接口,是一个空接口,为对象提供序列化和反序列化的操作。可以通过 IO 流可轻松进行序列化和反序列化。
serialVersionUID 是用来辅助序列化和反序列化过程的。

private static final long serialVersionUID = 1L;

原则上反序列后的数据中的 serialVersionUID 只有和当前类的 serialVersionUID 相同才能正常的被反序列化。注意以下两点:

  • 静态成员变量属于类不属于对象,不参与序列化过程
  • 用 transient 关键则标记的成员变量不参与序列化过程
public transient String like;

Bundle setbundle=new Bundle();
Person person=new Person(111,"姓名","篮球");
setbundle.putSerializable("person",person);

if (bundle.containsKey("person")) 
    Person p= (Person)bundle.getSerializable("person");
    Logger.e("id="+p.getUserid());
    Logger.e("name="+p.getName());
    Logger.e("like="+p.getLike());

打印出来like为null            

Parcelable

Parcelable 也是一个接口,Parcelable 是 Android 上的序列化方式,比较适合用在 Android 开发上。示例如下:

public class Student implements Parcelable 

    public int sId;

    public String name;


    @Override
    public int describeContents() 
        return 0;
    

    @Override
    public void writeToParcel(Parcel dest, int flags) 
        dest.writeInt(this.sId);
        dest.writeString(this.name);
    

    public Student() 
    

    protected Student(Parcel in) 
        this.sId = in.readInt();
        this.name = in.readString();
    

    public static final Parcelable.Creator<Student> CREATOR = new Parcelable.Creator<Student>() 
        @Override
        public Student createFromParcel(Parcel source) 
            return new Student(source);
        

        @Override
        public Student[] newArray(int size) 
            return new Student[size];
        
    ;


    public Student(int sId, String name) 
        this.sId = sId;
        this.name = name;
    

    public int getsId() 
        return sId;
    

    public void setsId(int sId) 
        this.sId = sId;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

Parcelable 接口定义在封送/解封送过程中混合和分解对象的契约。Parcelable 接口的底层是 Parcel 容器对象。Parcel 类是一种最快的序列化/反序列化机制,专为 Android 中的进程间通信而设计。该类提供了一些方法来将成员容纳到容器中,以及从容器展开成员。在序列化过程中需要实现的功能有序列化、反序列化和内容描述。序列化功能由 writeToParcel 方法完成,最终是通过 Parcel 中的一系列 write 方法来完成。反序列化由 CREATOR 来完成,其内部标明了如何创建序列化对象和数组,并通过 Parcel 的一系列 read 方法来完成反序列化过程。内容描述功能由 describeContents 方法来完成,几乎在所有情况下这个方法都应该返回 0,仅当当前对象中存在文件描述符时返回 1。系统为我们提供了许多实现了 Parcelable 接口的类,它们都是可以直接序列化对的,比如 Intent、Bundle、Bitmap 等,同时 List 和 Map 也可以序列化,前提是它们里面的每一个元素都可以序列化。

Serializable、Parcelable 的区别

  • Serializable 使用了反射,虽然使用简单但大量的 io 操作使得开销大、效率慢。序列化的时候创建许多的临时对象,容易触发垃圾回收。
  • Parcelable 实现原理是将一个完整的对象进行分解;效率高;主要用在内存序列化上。
  • 通过 Parcelable 将对象序列化到存储设备上或者通过网络传输也都是可以的,但是这个过程复杂,这两种情况建议还是用 Serializable。
  • Parcelable 不能使用在要将数据存储在磁盘上的情况,因为 Parcelable 不能很好的保证数据的持续性在外界有变化的情况下。不推荐使用Parcelable进行数据持久化。尽管 Serializable 效率低点,但此时还是建议使用 Serializable。

通过 Bundle 传递注意对象大小

Intent 中的 Bundle 是在使用 Binder 机制进行数据传递的,能使用的 Binder 的缓冲区是有大小限制的(有些手机是2M),而一个进程默认有16个 binder 线程,所以一个线程能占用的缓冲区就更小了(以前做过测试,大约一个线程可以占用128KB)。如果超过大小会报“The Binder transaction failed because it was too large.”这类 TransactionTooLargeException 异常。
因此,使用 Intent 在 Activity 之间传递 List 和 Bitmap 对象是有风险的。

以上是关于SerializableParcelable 的简介及区别的主要内容,如果未能解决你的问题,请参考以下文章

iOS 参考的简书作者

有理数的简算

userdel的简答用法

scala关于HelloWorld的简解

TCP协议的简解

javascript中闭包最简单的简绍