Android 序列化 Serializable 和 Parcelable 应用和区别
一:Serializable
1. 什么是序列化
将一个类对象转换成可存储,可传输状态的过程。
2. 什么是 Serializable 接口
一个对象序列化的接口,一个类只有实现了 Serializable 接口,它的对象能力被序列化。
3. 为什么要序列化对象
1. 把对象转换为字节序列的过程称为对象的序列化
2. 把字节序列复原为对象的过程称为对象的反序列化
4. 序列化用处
1. 想把对象的状态信息通过网络进行传输
2. 须要把对象长久化存储,存储在文件,数据库等
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
}
当我跟进去, 发现 Serializable 是一个空接口,一个接口什么都没有,咱们能够将它了解成一个标识接口
例如:在课堂上有位学生遇到一个问题,于是举手向老师求教,这时老师帮他解答,那么这位学生的举手其实就是一个标识,本人解决不了问题求教老师帮忙解决。在 Java 中的这个 Serializable 接口其实是给 jvm 看的,告诉 jvm,我不对这个类做序列化了,你 (jvm) 帮我序列化就好了。
5. 为什么要定义 serialVersionUID 变量
从阐明中能够看出,如果咱们没有本人申明一个 serialVersionUID 变量,接口会默认生成一个 serialVersionUID
* 然而强烈建议用户自定义一个 serialVersionUID,因为默认的 serialVersionUID 对于 class 的细节十分敏感,反序列化时可能会导致
InvalidClassException 这个异样。*
5.transient 关键字
用来示意一个成员变量不是该对象序列化的一部分。当一个对象被序列化的时候,transient 型变量的值不包含在序列化后果中。注:static 润饰的动态变量人造的就是不可序列化的
private static final long serialVersionUID = 1L;
private String name;
private transient int age;
transient 关键字只能润饰变量,而不能润饰办法和类。
被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。
二:Parcelable
Parcelable 是 Android 为咱们提供的序列化的接口,Parcelable 的效率绝对于 Serializable 也高许多。
Parcelable 不能应用在要将数据存储在磁盘上状况
在内存中应用 Parcelable 性能优于 Serializable
public class User implements Parcelable {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 从序列化后的对象中创立原始数据 */
protected User(Parcel in) {name = in.readString();
age = in.readInt();}
/**
* 序列化:将以后对象写入序列化构造中
*/
@Override
public void writeToParcel(Parcel dest, int flags) {dest.writeString(name);
dest.writeInt(age);
}
/**
* 以后对象的内容形容,存在文件描述符时返回 1,其余全返回 0
*/
@Override
public int describeContents() {return 0;}
/**
* 反序列化
*/
public static final Creator<User> CREATOR = new Creator<User>() {
/**
* 将序列化对象中创立原始数据 */
@Override
public User createFromParcel(Parcel in) {return new User(in);
}
/**
* 创立指定长度的原始对象数组 */
@Override
public User[] newArray(int size) {return new User[size];
}
};
@Override
public String toString() {
return "User{" +
"name='" + name + '''+", age="+ age +'}';
}
}
1.Parcel 英文译为包裹,Android 采纳这个词示意封装音讯的数据。这个通过 IBinder 通信的音讯载体。Parcel 用来存放数据的内存(RAM), 而不是永恒介质。
// 获取一个 Parcel 容器
Parcel parcel=Parcel.obtain();
// 须要序列化的对象
User user=new User("mike",13);
// 把对象写入 Parcel
parcel.writeParcelable(user,0);
//Parcel 读写共用一个地位计数,这里肯定要重置一下以后的地位
parcel.setDataPosition(0);
// 读取 Parcel
User user1=parcel.readParcelable(User.class.getClassLoader());
Log.d("LoginActivity",user1.toString());
调用 parcel.writeParcelable(user,0); 源码解析
public final void writeParcelable(@Nullable Parcelable p, int parcelableFlags) {
// 判断 p 是否为空
if (p == null) {writeString(null);
return; }
// 先写入 P 的类名(user 就是 p 类类名)writeParcelableCreator(p);
// 调用咱们重写的 writeToParcel 办法,按程序写入
p.writeToParcel(this, parcelableFlags);
}
/** @hide */
@UnsupportedAppUsage
public final void writeParcelableCreator(@NonNull Parcelable p) {
// 写入 p 类的类名
String name = p.getClass().getName();
writeString(name);
}
调用 parcel.readParcelable(User.class.getClassLoader()); 源码解析
public final <T extends Parcelable> T readParcelable(@Nullable ClassLoader loader) {
// 调用 readParcelableCreator
// 这时咱们获取就是咱们自定义的 CREATOR
Parcelable.Creator<?> creator = readParcelableCreator(loader);
if (creator == null) {return null;}
// 判断以后 creator 是不是 Parcelable.ClassLoaderCreator<?> 的实例
if (creator instanceof Parcelable.ClassLoaderCreator<?>) {// 如果是的话,,咱们调用 reateFromParcel(this, loader)
Parcelable.ClassLoaderCreator<?> classLoaderCreator =
(Parcelable.ClassLoaderCreator<?>) creator;
return (T) classLoaderCreator.createFromParcel(this, loader);
}
// 调用咱们自定义的 CREATOR 中重写的 createFromParcel 办法
return (T) creator.createFromParcel(this);
}
public final Parcelable.Creator<?> readParcelableCreator(@Nullable ClassLoader loader) {
// 首先把类名读取进去
String name = readString();
if (name == null) {return null;}
Parcelable.Creator<?> creator;
//mCreators 做了一下缓存,如果之前某个 classloader 把一个 parcelable 的 Creator 获取过
// 那么就不须要通过反射去查找了
synchronized (mCreators) {HashMap<String,Parcelable.Creator<?>> map = mCreators.get(loader);
if (map == null) {map = new HashMap<>();
mCreators.put(loader, map);
}
creator = map.get(name);
if (creator == null) {
try {// If loader == null, explicitly emulate Class.forName(String) "caller
// classloader" behavior. ClassLoader parcelableClassLoader =
(loader == null ? getClass().getClassLoader() : loader);
// Avoid initializing the Parcelable class until we know it implements
// Parcelable and has the necessary CREATOR field. http://b/1171613. Class<?> parcelableClass = Class.forName(name, false /* initialize */,
parcelableClassLoader);
if (!Parcelable.class.isAssignableFrom(parcelableClass)) {
throw new BadParcelableException("Parcelable protocol requires subclassing"
+ "from Parcelable on class" + name);
}
Field f = parcelableClass.getField("CREATOR");
if ((f.getModifiers() & Modifier.STATIC) == 0) {
throw new BadParcelableException("Parcelable protocol requires"
+ "the CREATOR object to be static on class" + name);
}
Class<?> creatorType = f.getType();
if (!Parcelable.Creator.class.isAssignableFrom(creatorType)) {// Fail before calling Field.get(), not after, to avoid initializing
// parcelableClass unnecessarily. throw new BadParcelableException("Parcelable protocol requires a"
+ "Parcelable.Creator object called"
+ "CREATOR on class" + name);
}
creator = (Parcelable.Creator<?>) f.get(null);
}
catch (IllegalAccessException e) {Log.e(TAG, "Illegal access when unmarshalling:" + name, e);
throw new BadParcelableException("IllegalAccessException when unmarshalling:" + name);
}
catch (ClassNotFoundException e) {Log.e(TAG, "Class not found when unmarshalling:" + name, e);
throw new BadParcelableException("ClassNotFoundException when unmarshalling:" + name);
}
catch (NoSuchFieldException e) {
throw new BadParcelableException("Parcelable protocol requires a"
+ "Parcelable.Creator object called"
+ "CREATOR on class" + name);
}
if (creator == null) {
throw new BadParcelableException("Parcelable protocol requires a"
+ "non-null Parcelable.Creator object called"
+ "CREATOR on class" + name);
}
map.put(name, creator);
}
}
return creator;
}