【安卓】Android 使用序列化Serializable和Parcelable

Android 使用序列化Serializable和Parcelable

Rocky_ruan发布于 57 分钟前

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)帮我序列化就好了。

【安卓】Android 使用序列化Serializable和Parcelable
5.为什么要定义serialVersionUID变量
【安卓】Android 使用序列化Serializable和Parcelable
从说明中可以看出,如果我们没有自己申明一个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;

}

android序列化

阅读 25发布于 57 分钟前

本作品系原创,采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议

avatar

Rocky_ruan

1 声望

0 粉丝

0 条评论

得票时间

avatar

Rocky_ruan

1 声望

0 粉丝

宣传栏

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)帮我序列化就好了。

【安卓】Android 使用序列化Serializable和Parcelable
5.为什么要定义serialVersionUID变量
【安卓】Android 使用序列化Serializable和Parcelable
从说明中可以看出,如果我们没有自己申明一个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;

}

以上是 【安卓】Android 使用序列化Serializable和Parcelable 的全部内容, 来源链接: utcz.com/a/108960.html

回到顶部