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; }