美文网首页
Serializable和Parcelable区别

Serializable和Parcelable区别

作者: code希必地 | 来源:发表于2020-11-30 16:09 被阅读0次

当我们需要使用Intent或Binder传递对象数据时,就需要用到Serializable和Parcelable。

1、Serializable

Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化的对象可以在网络上进行传输,也可以存储到本地。

1.1、Serializable简介

Serializable是java提供的一个序列化接口,是一个空接口,为对象提供标准的序列化和反序列化操作。使用起来非常简单,只需要让对象实现Serializable接口即可。

public class Persion implements Serializable{
  private static final  long serialVersionUID=1L;
  public String name;
  public String sex;
  public int age;

  public Persion(String name,String sex,int age){
         this.name=name;
         this.sex=sex;
         this.age=age;
  }
}

1.2、Serializable的序列化和反序列化

在上节中的Person类实现了Serializable接口,这样Person就变成了可序列化的了,我们就可以使用Intent进行数据的传递了。使用如下:

Person p=new Person("张三丰","男",100);
Intent intent=new Intent(this,TestActivity.class);
intent.putExtra("person_data",p);
startActivity(intent)

看下在TestActivity中进行数据的接收:

Person p=getIntent().getSerializableExtra("person_data");

这种传递对象的工作原理就是:先将一个对象序列化成可存储或可传输的状态,传递给下一个Activity,在下一个Activity需要将其反序列化成一个新的对象。注意这两个对象中的数据虽然完全相同,但并不是相同的对象。
下面再看下如何将对象序列化到本地,并从本地反序列化得到对象。具体代码如下:

 //序列化对象到本地
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cache.txt"));
        Person p1 = new Person();
        out.writeObject(p1);
        out.close();

        //反序列化对象
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("cache.txt"));
        Person p2 = (Person) in.readObject();
        in.close();

同样的序列化到本地的对象和反序列化得到的对象虽然数据相同,但是并不是一个对象。

1.3、serialVersionUID的作用

还记的上面我们在定义Person类时中定义了一个

private static final  long serialVersionUID=1L;

那么这个serialVersionUID有什么作用呢?serialVersionUID主要用于反序列化,在反序列化时会检测文件中的serialVersionUID和当前类中的serialVersionUID是否一致,若不一致则会反序列化失败。所以一般我们应该指定serialVersionUID,否则当序列化的类中的变量的数量或类型发生变化时,系统默认生成的serialVersionUID就会发生变化,这就和之前序列化时的serialVersionUID不一致了,所以无法正常反序列化。

2、Parcelable

除了Serializable之外,我们还可以使用Parcelable来实现同样的效果。Parcelable是Android提供的,Parcelable的实现原理是将一个完整的对象进行拆解。而分解后的每一部分是可序列化的。而Serializable是将整个对象进行序列化。
下面看下Parcelable的使用

public class Person implements Parcelable {
    private String name;
    private int age;


    protected Person(Parcel in) {
        name = in.readString();
        age = in.readInt();
    }

    public static final Creator<Person> CREATOR = new Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel in) {
            return new Person(in);
        }

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(name);
        parcel.writeInt(age);
    }
}

可以看到我们重写了方法describeContents()writeToParcel()describeContents()方法直接返回0即可,而在writeToParcel()方法中我们需要调用parcel.writeXXX()将Person中的字段一 一写出。
除此之外,我们还必须在Person类中提供一个名为CREATOR的匿名类实现。这里创建了Creator接口的实现,在其中重写了createFromParcel()newArray(),在createFromParcel()中需要创建一个Person对象返回,并读取刚才写出的name和age字段。其中name和age通过in.readXXX()读取的,注意这里的读取顺序要和写入的顺序一致。newArray()只需要返回Person数组即可。
使用Intent传递对象的具体使用如下:

Person p=new Person("张三丰","男",100);
Intent intent=new Intent(this,TestActivity.class);
intent.putExtra("person_data",p);
startActivity(intent)

但是在TestActivity中获取数据的代码有所不同

Person p=(Person) intent.getParcelableExtra("person_data");

3、选择的原则

  • 1、如果仅仅是在内存中使用,比如Activity、Service间进行对象的传递 ,推荐使用Parcelable,因为Parcelable的性能比Serializable高很多。因为Serializable在序列化时产生很多临时变量,从而引起频繁的GC。
  • 2、如果是持久化操作,推荐使用Serializable,因为使用Parceable不能很好的保证数据的连续性。

4、本质的区别

  • 1、Serializable的本质是使用了反射,序列化的过程比较慢,这种机制在序列化的时候会创建很多临时的对象,比引起频繁的GC、
  • 2、Parcelable方式的本质是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的类型,这样就实现了传递对象的功能了。

相关文章

网友评论

      本文标题:Serializable和Parcelable区别

      本文链接:https://www.haomeiwen.com/subject/smirwktx.html