1、Parcelable和Serializable有什么用,它们有什么差别?.
Serializable是Java为我们提供的一个标准化的序列化接口,那什么是序列化呢? ---- 简单来说就是将对象转换为可以传输的二进制流(二进制序列)的过程,这样我们就可以通过序列化,转化为可以在网络传输或者保存到本地的流(序列),从而进行传输数据 ,那反序列化就是从二进制流(序列)转化为对象的过程.
Serializable可以保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的
Android的Parcelable的设计初衷是因为Serializable效率过慢,为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable是通过IBinder通信的消息的载体。
区别:
(1)性能上
Serializable : 序列化和反序列化都需要操作大量的IO,所以性能比较差
Parcelable : 不需要操作大量的IO,它基于Parcel提供了一套机制,可以将序列化之后的
数据写入到一个共享内存中,其他进程通过Parcel可以从这块共享内存中读出字节流,并
反序列化成对象。号称比Serializable性能快10倍的效率
(2)使用上
Serializable : 是Java提供的序列化接口,可以在任何java语言上使用,实现起来
比较简单,实现Serializable接口即可.序列化机制依赖于一个Long类型serialVersionUID,
如果没有显示指定serialVersionUID 该值,系统基于该类计算一个值。如果类的结构发生
变化就会导致自动计算的serialVersionUID 值不同。如果:序列化之后类如果新增一个字
段,反序列化过程就会失败,一般会报java.io.InvalidClassException:
W/System.err: java.io.InvalidClassException: com.charles.plugin.gradledemo.parcelable.MyUserModel; Incompatible class (SUID):
com.charles.plugin.gradledemo.parcelable.MyUserModel: static final long
serialVersionUID =-2530467661280717770L; but expected
com.charles.plugin.gradledemo.parcelable.MyUserModel: static final long
serialVersionUID =2955893512855837466L;
而如果显示指定了serialVersionUID,只要类结构不发生重大变化,比如改类型或者字段
名。仅仅添加字段和删除字段都能反序列成功.
Parcelable : 是 Android 提供的序列化接口,使用起来比较麻烦要实现describeContents()
和 writeToParcel() 放法,并且必须要有一个非空的静态变量 CREATOR,我们提供一个
Parcelable.Creator<T>匿名内部类,类似
public static final Creator<UserModel> CREATOR = new Creator<UserModel>() {
@Override
public UserModel createFromParcel(Parcel in) {
UserModel userModel = new UserModel();
userModel.setAge(in.readString());
userModel.setName(in.readString());
userModel.setSex(in.readString());
return userModel;
}
@Override
public UserModel[] newArray(int size) {
return new UserModel[size];
}
};
(3) 二者的选取规则
内存序列化上选择Parcelable, 存储到设备或者网络传输上选择Serializable
(当然Parcelable也可以但是稍显复杂)
2、自定义一个类让其实现Parcelable,大致流程是什么?
(1)createFromParcel(Parcel in): 从序列化后的对象中创建原始对象
(2)newArray(int size):创建指定长度的原始对象数组
(3)writeToParcel:将当前对象写入序列化结构中。flags表示值0或1,为1时标示当前对象需要作为返回值返回,不能立即释放资源。
(4)describeContents:返回当前对象的内容描述,返回1时表示含有文件描述符。
public class UserModel implements Parcelable {
public static final Creator<UserModel> CREATOR = new Creator<UserModel>() {
@Override
public UserModel createFromParcel(Parcel in) {
UserModel userModel = new UserModel();
userModel.setAge(in.readString());
userModel.setName(in.readString());
userModel.setSex(in.readString());
return userModel;
}
@Override
public UserModel[] newArray(int size) {
return new UserModel[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
// 1.必须按成员变量声明的顺序封装数据,不然会出现获取数据出错
// 2.序列化对象
parcel.writeString(age);
parcel.writeString(name);
parcel.writeString(sex);
}
public UserModel(String name, String age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
private String name;
private String age;
private String sex;