Serializable和Parcelable的区别及使用方式

对象在传递过程中必须进行序列化方可传递,android序列化有两种方式,分别是继承Serializable和Parcelable接口。两种都是用于支持序列化、反序列化话操作,两者最大的区别在于存储媒介的不同,Serializable使用IO读写存储在硬盘上,而Parcelable是直接在内存中读写,很明显内存的读写速度通常大于IO读写,Serializable是java序列化接口,使用起来简单但是开销大序列化反序化都要进行大量的I/O操作,Parcelable是Android中的序列化方式,所以在Android中通常优先选择Parcelable。平日开发中Serializable比较容易上手直接继承接口即可,Parcelable使用较为复杂,但是性能高于Serializable十倍。

当对象序列化到存储设备或者通过网络传输的时候最好是使用Serializable,Parcelable也可以用做该过程,但是使用比较复杂所以建议使用Serializable。其他情况使用建议Parcelable

下面介绍Serializable的使用方式:

Serializable使用简单。对象直接继承该接口即可。

public class User implements Serializable{
    private int id;
    private String username;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

在传参的时候使用intent或者是bundle。传递方式如下

Intent intent = new Intent(MainActivity.this,SecondActivity.class);
intent.putExtra("user",user);
Bundle bundle = intent.getExtras();
bundle.putSerializable("user1",user);
intent.putExtras(bundle);
startActivity(intent);

获取方式如下:

Intent intent = getIntent();
Bundle bundle = intent.getExtras();
User user= (User) intent.getSerializableExtra("user");
User user1 = (User) bundle.getSerializable("user1");

接下来讲一下Parcelable的使用,为了方便学习我把几种常用的类型都写上了:

这里面很多方法都是系统生成的。大家自己写上自己需要的构造器即可。这里包括序列化和反序列化两个方法,因此有新对象加入的时候两个方法必须都写上相应的过程。先简单介绍以下几个方法

public static final Creator CREATOR = new Creator() {
    @Override
    public Teacher createFromParcel(Parcel in) {
//从序列化的对象创建原始对象
        return new Teacher(in);
    }

    @Override
    public Teacher[] newArray(int size) {
//创建指定长度的原始数组
        return new Teacher[size];
    }
};
返回当前对象的内容描述,如果含有文件描述则返回1,否则返回0一般都返回0.
@Override
public int describeContents() {
    //固定写法
    return 0;
}
从序列化的对象中创建原始对象即反序列化
protected Teacher(Parcel in) {
    //顺序一定要对应上
    id = in.readInt();
    //读取的String转为布尔类型
    normalStatus = Boolean.valueOf(in.readString());
    gmtCreated = in.readLong();
    name = in.readString();
    //读取的price为String类型, 需要转为BigDecimal
    price = new BigDecimal(in.readString());
    //读取对象实现了Parcelable接口的对象
    secondBean = in.readParcelable(Student.class.getClassLoader());
    //读取实现了Parcelable接口的对象List
    secondBeanList = in.readArrayList(Student.class.getClassLoader());
    //创建(读取)int类型数组, 其他数组类型以此类推
    numberArray = in.createIntArray();
    map = in.readHashMap(String.class.getClassLoader());
}
序列化过程:
将当前对象写入序列化结构中,其中flags有两个值,0或1,当为1时标志当前对象需要作为返回值返回,不能立即释放资源。几乎所有情况都为0;
@Override
public void writeToParcel(Parcel out, int flags) {
    //切记非常重要, 写数据(out.write...)和下面的读数据(in.read...)的顺序一定要和声明的属性顺序对应上, 不然会因为读写的数据类型不一致而报异常
    //普通数据类型int, double, String等等, 用法以此类推
    out.writeInt(id);
    //由于没有写入布尔数据类型的方法, 需要把布尔数据类型转换为String
    out.writeString(String.valueOf(normalStatus));
    out.writeLong(gmtCreated);
    out.writeString(name);
    //判空, 因为如果price为null, 也会报异常, 没有写入BigDecimal的数据类型, 需要转为String
    out.writeString(price == null ? "0" : price.toString());
    //写入对象, 该对象必须也要实现Parcelable接口
    out.writeParcelable(secondBean, flags);
    //写入List集合
    out.writeList(secondBeanList);
    //写入int类型数组, 其他的数组类型以此类推
    out.writeIntArray(numberArray);
    out.writeMap(map);
}

明白这几个过程后添加元素主要的操作是在序列化和反序列化的方法中即protected Teacher(Parcel in)和writeToParcel中

public class Teacher implements Parcelable {
    private int id;
    private boolean normalStatus;
    private long gmtCreated;
    private String name;
    private BigDecimal price;
    private Student secondBean;
    private List secondBeanList;
    private int[] numberArray;
    private Map map;


    public Teacher() {

    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public boolean isNormalStatus() {
        return normalStatus;
    }

    public void setNormalStatus(boolean normalStatus) {
        this.normalStatus = normalStatus;
    }

    public long getGmtCreated() {
        return gmtCreated;
    }

    public void setGmtCreated(long gmtCreated) {
        this.gmtCreated = gmtCreated;
    }

    public String getName() {
        return name;
    }

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

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public Student getSecondBean() {
        return secondBean;
    }

    public void setSecondBean(Student secondBean) {
        this.secondBean = secondBean;
    }

    public List getSecondBeanList() {
        return secondBeanList;
    }

    public void setSecondBeanList(List secondBeanList) {
        this.secondBeanList = secondBeanList;
    }

    public int[] getNumberArray() {
        return numberArray;
    }

    public void setNumberArray(int[] numberArray) {
        this.numberArray = numberArray;
    }

    public Map getMap() {
        return map;
    }

    public void setMap(Map map) {
        this.map = map;
    }

    //固定写法, 只用修改Creator的泛型
    public static Creator getCREATOR() {
        return CREATOR;
    }

    //固定写法, 只用修改Creator的泛型
    public static final Creator CREATOR = new Creator() {
        @Override
        public Teacher createFromParcel(Parcel in) {
            return new Teacher(in);
        }

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

    @Override
    public int describeContents() {
        //固定写法
        return 0;
    }

    protected Teacher(Parcel in) {
        //顺序一定要对应上
        id = in.readInt();
        //读取的String转为布尔类型
        normalStatus = Boolean.valueOf(in.readString());
        gmtCreated = in.readLong();
        name = in.readString();
        //读取的price为String类型, 需要转为BigDecimal
        price = new BigDecimal(in.readString());
        //读取对象实现了Parcelable接口的对象
        secondBean = in.readParcelable(Student.class.getClassLoader());
        //读取实现了Parcelable接口的对象List
        secondBeanList = in.readArrayList(Student.class.getClassLoader());
        //创建(读取)int类型数组, 其他数组类型以此类推
        numberArray = in.createIntArray();
        map = in.readHashMap(String.class.getClassLoader());
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        //切记非常重要, 写数据(out.write...)和下面的读数据(in.read...)的顺序一定要和声明的属性顺序对应上, 不然会因为读写的数据类型不一致而报异常
        //普通数据类型int, double, String等等, 用法以此类推
        out.writeInt(id);
        //由于没有写入布尔数据类型的方法, 需要把布尔数据类型转换为String
        out.writeString(String.valueOf(normalStatus));
        out.writeLong(gmtCreated);
        out.writeString(name);
        //判空, 因为如果price为null, 也会报异常, 没有写入BigDecimal的数据类型, 需要转为String
        out.writeString(price == null ? "0" : price.toString());
        //写入对象, 该对象必须也要实现Parcelable接口
        out.writeParcelable(secondBean, flags);
        //写入List集合
        out.writeList(secondBeanList);
        //写入int类型数组, 其他的数组类型以此类推
        out.writeIntArray(numberArray);
        out.writeMap(map);
    }
}

Parcelable序列化必须保证里面的对象都能序列化,改对象中包含Student,这个对象也必须是继承Parcelable序列化的:

public class Student implements Parcelable {
    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Student() {
    }

    public Student(int id) {
        this.id = id;
    }

    protected Student(Parcel in) {
        id = in.readInt();
    }

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

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

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

    @Override
    public void writeToParcel(Parcel out, int flag) {
        out.writeInt(id);
    }

    public static Creator getCREATOR() {
        return CREATOR;
    }
}

传参的过程如下:

Intent intent = new Intent(FirstParcelableActivity.this,SecondParcelableActivity.class);
intent.putExtra("parcelable",mainBean);
Bundle bundle = intent.getExtras();
bundle.putParcelable("parcelable1",mainBean);
intent.putExtras(bundle);
startActivity(intent);

获得数据的过程如下:

Intent intent = getIntent();
Teacher mainBean = intent.getParcelableExtra("parcelable");
Bundle bundle = getIntent().getExtras();
Teacher mainBean1 = bundle.getParcelable("parcelable1");

最后上demo的链接。https://github.com/Maliola/XuLieHua.git

你可能感兴趣的:(Serializable和Parcelable的区别及使用方式)