Android 序列化 Serializable 和 Parcelable

文章目录

[TOC]

一、什么是序列化


序列化 (Serialization) 将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

二进制序列化保持类型保真度,这对于在应用程序的不同调用之间保留对象的状态很有用。例如,通过将对象序列化到剪贴板,可在不同的应用程序之间共享对象。您可以将对象序列化到流、磁盘、内存和网络等等。远程处理使用序列化“通过值”在计算机或应用程序域之间传递对象。

二、序列化方法


  • Serialization 是 Java 所提供的序列化接口,它是一个空的接口,只为对象提供标准的序列表和反序列化操作。
  • Parcelable Android 特有的序列化接口。

1、Serialization 接口

Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。

Serializable特点:

  • 简单易用,只需要实体类继承 Serializable 即可
  • 可序列化类中,未实现 Serializable 的属性状态无法被序列化/反序列化
  • 一个实现序列化的类,它的子类也是可序列化的

Serializable序列化实例:

  1. public class User implements Serializable {
  2. private static final long serialVersionUID = 123456789L;
  3. private int userId;
  4. private String userName;
  5. public int getUserId() {
  6. return userId;
  7. }
  8. public void setUserId(int userId) {
  9. this.userId = userId;
  10. }
  11. public String getUserName() {
  12. return userName;
  13. }
  14. public void setUserName(String userName) {
  15. this.userName = userName;
  16. }
  17. }

序列化和反序列化的过程

  1. // 序列化过程
  2. User user = new User(1, "张三");
  3. ObjectOutputStream objectOutputStream;
  4. {
  5. try {
  6. objectOutputStream = new ObjectOutputStream(new FileOutputStream("cache.txt"));
  7. objectOutputStream.writeObject(user);
  8. objectOutputStream.close();
  9. } catch (IOException e) {
  10. e.printStackTrace();
  11. }
  12. }
  13. // 反序列化过程
  14. ObjectInputStream objectInputStream;
  15. {
  16. try {
  17. objectInputStream = new ObjectInputStream(new FileInputStream("cache.txt"));
  18. try {
  19. User newUser = (User) objectInputStream.readObject();
  20. objectInputStream.close();
  21. } catch (ClassNotFoundException e) {
  22. e.printStackTrace();
  23. }
  24. } catch (IOException e) {
  25. e.printStackTrace();
  26. }
  27. }

从上面的实例可以看出Serializable序列化很简单,只需要设置一个serialVersionUID 即可。

其中serialVersionUID可以设置,也可以不设置,如果不进行设置系统也会生成默认的值,那么为什么一定要设置serialVersionUID的值呢。serialVersionUID的详细工作机制是这样的:序列化的时候系统会把当前列的serialVersionUID写入序列化的文件中(也可能是其他的中介),当反序列化的时候系统会去检测文中的serialVersionUID,看他是否和当前类的serialVersionUID一致,如果一致就说明序列化的类和的版本和当前类的版本是相同的,这个时候可以成功反序列化,否则就说明当前类和序列化的类相比发生了某些变化,比如当前类或成员变量发生了变化系统就会重新计算当前类的hash值并把它赋值给serialVersionUID,这个时候当前类的serialVersionUID就和序列化数据中的serialVersionUID不一致,于是反序列化就会失败,程序就会出现InvalidClassException错误。所以为了避免反序列化的失败尽量手动设置serialVersionUID的值。

2、Parcelable 接口

Parcelable接口是 Android 专用的序列化接口,在性能上完胜Serializable接口。

Parcelable特点:

  • 比起 Serializable,Parcelable 开销更小效率更高。
  • 序列化过程较复杂。其实实现 Parcelable 接口的方法是可以用插件直接生成的。
  • Parcelable 实现主要还是解决 Android 平台内存紧缺的问题。

Parcelable序列化实例:

  1. public class User implements Parcelable {
  2. private int userId;
  3. private String userName;
  4. public User(int userId, String userName) {
  5. this.userId = userId;
  6. this.userName = userName;
  7. }
  8. public int getUserId() {
  9. return userId;
  10. }
  11. public void setUserId(int userId) {
  12. this.userId = userId;
  13. }
  14. public String getUserName() {
  15. return userName;
  16. }
  17. public void setUserName(String userName) {
  18. this.userName = userName;
  19. }
  20. /**
  21. * 自动创建的的构造器,使用反序列化得到的 Parcel 构造对象,
  22. * 从序列化后的对象中创建原始对象
  23. * @param in
  24. */
  25. protected User(Parcel in) {
  26. userId = in.readInt();
  27. userName = in.readString();
  28. }
  29. /**
  30. * 内容描述
  31. * @return
  32. */
  33. @Override
  34. public int describeContents() {
  35. //几乎都返回 0,除非当前对象中存在文件描述符时为 1
  36. return 0;
  37. }
  38. /**
  39. * 序列化,将当前对象写入序列化结构中,其中flags标识有两种值:0或者1,
  40. * 为1时标识当前对象需要作为返回值返回,不能立即释放资源,几乎所有情况都为0
  41. * @param dest
  42. * @param flags
  43. */
  44. @Override
  45. public void writeToParcel(Parcel dest, int flags) {
  46. dest.writeInt(userId);
  47. dest.writeString(userName);
  48. }
  49. /**
  50. * 反序列化
  51. */
  52. public static final Creator<User> CREATOR = new Creator<User>() {
  53. /**
  54. * 反序列创建对象,从序列化后的对象中创建原始对象
  55. * @param in
  56. * @return
  57. */
  58. @Override
  59. public User createFromParcel(Parcel in) {
  60. return new User(in);
  61. }
  62. /**
  63. * 反序列创建对象数组,创建指定长度的原始对象数组
  64. * @param size
  65. * @return
  66. */
  67. @Override
  68. public User[] newArray(int size) {
  69. return new User[size];
  70. }
  71. };
  72. }

三、Serializable 和 Parcelable 优缺点:


  • Serializable 序列化

    • 代码量少,写起来方便。
    • 使用反射机制序列化过程较慢,序列化时会创建许多临时对象,容易触发垃圾回收。
  • Parcelable 序列化

    • 代码量比较多
    • 速度快,效率高。实现原理是将一个完整的对象进行分解,分解后的每一个部分都是Intent所支持的数据类型。

(完)