版权声明:本文为HaiyuKing原创文章,转载请注明出处!

前言

简单记录下序列化Serializable和Parcelable的使用方法。

Android中Intent如果要传递类对象,可以通过两种方式实现

  • 方式一:Serializable,要传递的类实现Serializable接口传递对象,
  • 方式二:Parcelable,要传递的类实现Parcelable接口传递对象。

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

Parcelable(android 专用):
除了Serializable之外,使用Parcelable也可以实现相同的效果,
不过不同于将对象进行序列化,Parcelable方式的实现原理是将一个完整的对象进行分解,
而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了。

实现序列化的作用

1)永久性保存对象,保存对象的字节序列到本地文件中;

2)通过序列化对象在网络中传递对象;

3)通过序列化在进程间传递对象。

选择序列化方法的原则

1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。

2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。

3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。

--摘自《序列化Serializable和Parcelable的理解和区别

 
简而言之:
Parcelable适合用在内存序列化上(也就是用于Intent间的数据传递);
Serializable适合用于将对象序列化到存储设备中或者将对象序列化后通过网络传输(一般用于Socket传输)。

使用方法

新建bean类

1、新建bean类implement Parcelable,重写以下方法

在Android Studio中可以自动引入:

  1. package com.why.project.androidcnblogsdemo.bean;
  2.  
  3. import android.os.Parcel;
  4. import android.os.Parcelable;
  5.  
  6. /**
  7. * Created by HaiyuKing
  8. * Used 用户bean类
  9. */
  10.  
  11. public class UserBean implements Parcelable{
  12. private String userName;
  13. private int userId;
  14. private boolean isVip;
  15.  
  16. //必须要添加
  17. public UserBean(){}
  18.  
  19. public String getUserName() {
  20. return userName;
  21. }
  22.  
  23. public void setUserName(String userName) {
  24. this.userName = userName;
  25. }
  26.  
  27. public int getUserId() {
  28. return userId;
  29. }
  30.  
  31. public void setUserId(int userId) {
  32. this.userId = userId;
  33. }
  34.  
  35. public boolean isVip() {
  36. return isVip;
  37. }
  38.  
  39. public void setVip(boolean vip) {
  40. isVip = vip;
  41. }
  42.  
  43. //默认返回0就可以
  44. //返回当前对象的内容描述,如果含有文件描述符,返回1,否则返回0,几乎所有情况都返回0
  45. @Override
  46. public int describeContents() {
  47. return 0;
  48. }
  49.  
  50. //将你的对象序列化为一个Parcel对象 即:将类的数据写入外部提供的Parcel中,打包需要传递的数据到Parcel容器保存,以便从 Parcel容器获取数据
  51. //将当前对象写入序列化结构中,其中flags标识有两种值:0或者1,为1时标识当前对象需要作为返回值返回,不能立即释放资源,几乎所有情况都为0
  52. @Override
  53. public void writeToParcel(Parcel parcel, int i) {
  54. parcel.writeString(userName);
  55. parcel.writeInt(userId);
  56. parcel.writeByte((byte) (isVip ? 1 : 0));
  57. }
  58.  
  59. public static final Creator<UserBean> CREATOR = new Creator<UserBean>() {
  60. //从序列化后的对象中创建原始对象
  61. @Override
  62. public UserBean createFromParcel(Parcel in) {
  63. return new UserBean(in);
  64. }
  65. //创建指定长度的原始对象数组
  66. @Override
  67. public UserBean[] newArray(int size) {
  68. return new UserBean[size];
  69. }
  70. };
  71. //从序列化后的对象中创建原始对象
  72. protected UserBean(Parcel in) {
  73. userName = in.readString();
  74. userId = in.readInt();
  75. isVip = in.readByte() != 0;
  76. }
  77. }

2、新建bean类implement Serializable,手动指定serialVersionUID的值

不指定serialVersionUID也可以实现序列化,但是应该指定。这个serialVersionUID是用来辅助序列化和反序列化过程的,原则上序列化后的数据中的serialVersionUID只有和当前类的serialVersionUID相同才能够正常地被反序列化。serialVersionUID的详细工作机制是这样的:序列化的时候系统会将当前类的serialVersionUID写入序列化的文件中(也可能是其他中介),当反序列化的时候系统会检测文件中的serialVersionUID,看它是否和当前类的serialVersionUID一致,如果一致就说明序列化的类的版本和当前类的版本是相同的,这个时候可以成功反序列化;否则就说明当前类和序列化的类相比发生了某些变化,比如成员变量的数量、类型可能发生了改变,这个时候是无法正常反序列化的,因此会报错

而手动指定serialVersionUID值的话,序列化和反序列化时两者的serialVersionUID是相同的。如果不手动指定serialVersionUID的值,反序列化时当前类发生了改变,比如增加或者删除成员变量,那么系统就会重新计算当前类的hash值并把赋值给serialVersionUID,这个时候当前类的serialVersionUID就和序列化数据中的serialVersionUID不一致,于是反序列化失败。

--摘自《Android开发艺术探索》

  1. package com.why.project.androidcnblogsdemo.bean;
  2.  
  3. import java.io.Serializable;
  4.  
  5. /**
  6. * Created by HaiyuKing
  7. * Used 书籍Bean类
  8. */
  9.  
  10. public class BookBean implements Serializable {
  11.  
  12. private static final long serialVersionUID = 123L;//手动指定值,默认是1L,可以是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段
  13.  
  14. private String bookName;
  15. private float bookPrice;
  16.  
  17. public String getBookName() {
  18. return bookName;
  19. }
  20.  
  21. public void setBookName(String bookName) {
  22. this.bookName = bookName;
  23. }
  24.  
  25. public float getBookPrice() {
  26. return bookPrice;
  27. }
  28.  
  29. public void setBookPrice(float bookPrice) {
  30. this.bookPrice = bookPrice;
  31. }
  32. }

(1)通过序列化在进程间传递对象【使用Parcelable】

顺带演示Serializable的使用方法。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical">
  7.  
  8. <Button
  9. android:id="@+id/btn_intent"
  10. android:layout_width="wrap_content"
  11. android:layout_height="wrap_content"
  12. android:text="通过序列化在进程间传递对象"
  13. android:layout_margin="10dp"/>
  14.  
  15. <Button
  16. android:id="@+id/btn_savefile"
  17. android:layout_width="wrap_content"
  18. android:layout_height="wrap_content"
  19. android:text="保存对象的字节序列到本地文件中"
  20. android:layout_margin="10dp"/>
  21.  
  22. <Button
  23. android:id="@+id/btn_openfile"
  24. android:layout_width="wrap_content"
  25. android:layout_height="wrap_content"
  26. android:text="反序列化从文件中读取对象数据"
  27. android:layout_margin="10dp"/>
  28. <TextView
  29. android:id="@+id/tv_showbookInfo"
  30. android:layout_width="match_parent"
  31. android:layout_height="wrap_content"/>
  32. </LinearLayout>

activity_serialize_one.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical">
  7.  
  8. <TextView
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content"
  11. android:text="通过序列化Parcelable传递的对象数据"/>
  12.  
  13. <TextView
  14. android:id="@+id/tv_Parcelable"
  15. android:layout_width="match_parent"
  16. android:layout_height="wrap_content"
  17. android:layout_marginBottom="10dp"/>
  18.  
  19. <TextView
  20. android:layout_width="wrap_content"
  21. android:layout_height="wrap_content"
  22. android:text="通过序列化Serializable传递的对象数据"/>
  23.  
  24. <TextView
  25. android:id="@+id/tv_Serializable"
  26. android:layout_width="match_parent"
  27. android:layout_height="wrap_content"/>
  28.  
  29. </LinearLayout>

activity_serialize_two.xml

  1. package com.why.project.androidcnblogsdemo.activity;
  2.  
  3. import android.content.Intent;
  4. import android.os.Bundle;
  5. import android.support.v7.app.AppCompatActivity;
  6. import android.view.View;
  7. import android.widget.TextView;
  8.  
  9. import com.why.project.androidcnblogsdemo.R;
  10. import com.why.project.androidcnblogsdemo.bean.BookBean;
  11. import com.why.project.androidcnblogsdemo.bean.UserBean;
  12.  
  13. import java.io.File;
  14. import java.io.FileInputStream;
  15. import java.io.FileOutputStream;
  16. import java.io.IOException;
  17. import java.io.ObjectInputStream;
  18. import java.io.ObjectOutputStream;
  19.  
  20. /**
  21. * Created by HaiyuKing
  22. * Used 序列化的首页界面
  23. */
  24.  
  25. public class SerializeOneActivity extends AppCompatActivity{
  26.  
  27. private UserBean mUserBean;
  28. private BookBean mBookBean;
  29.  
  30. @Override
  31. protected void onCreate(Bundle savedInstanceState) {
  32. super.onCreate(savedInstanceState);
  33. setContentView(R.layout.activity_serialize_one);
  34.  
  35. initDatas();
  36. initEvents();
  37.  
  38. }
  39.  
  40. private void initDatas() {
  41. mUserBean = new UserBean();
  42. mUserBean.setUserId(1111);
  43. mUserBean.setUserName("haiyuKing");
  44. mUserBean.setVip(true);
  45.  
  46. mBookBean = new BookBean();
  47. mBookBean.setBookName("Android开发艺术探索");
  48. mBookBean.setBookPrice(79f);
  49. }
  50.  
  51. private void initEvents() {
  52. findViewById(R.id.btn_intent).setOnClickListener(new View.OnClickListener() {
  53. @Override
  54. public void onClick(View view) {
  55. Intent intent = new Intent(SerializeOneActivity.this, SerializeTwoActivity.class);
  56. Bundle bundle = new Bundle();
  57. bundle.putParcelable("bundle_user",mUserBean);
  58. bundle.putSerializable("bundle_book",mBookBean);
  59. intent.putExtras(bundle);
  60. startActivity(intent);
  61. }
  62. });
  63.  
  64. findViewById(R.id.btn_savefile).setOnClickListener(new View.OnClickListener() {
  65. @Override
  66. public void onClick(View view) {
  67.  
  68. }
  69. });
  70.  
  71. findViewById(R.id.btn_openfile).setOnClickListener(new View.OnClickListener() {
  72. @Override
  73. public void onClick(View view) {
  74.  
  75. }
  76. });
  77. }
  78.  
  79. }

接收:

  1. package com.why.project.androidcnblogsdemo.activity;
  2.  
  3. import android.os.Bundle;
  4. import android.support.v7.app.AppCompatActivity;
  5. import android.widget.TextView;
  6.  
  7. import com.why.project.androidcnblogsdemo.R;
  8. import com.why.project.androidcnblogsdemo.bean.BookBean;
  9. import com.why.project.androidcnblogsdemo.bean.UserBean;
  10.  
  11. /**
  12. * Created by HaiyuKing
  13. * Used 序列化的第二个界面
  14. */
  15.  
  16. public class SerializeTwoActivity extends AppCompatActivity {
  17.  
  18. @Override
  19. protected void onCreate(Bundle savedInstanceState) {
  20. super.onCreate(savedInstanceState);
  21. setContentView(R.layout.activity_serialize_two);
  22.  
  23. TextView tv_Parcelable = findViewById(R.id.tv_Parcelable);
  24. TextView tv_Serializable = findViewById(R.id.tv_Serializable);
  25.  
  26. UserBean userBean = (UserBean)getIntent().getParcelableExtra("bundle_user");
  27. BookBean bookBean = (BookBean)getIntent().getSerializableExtra("bundle_book");
  28.  
  29. tv_Parcelable.setText(userBean.getUserId()+";"+userBean.getUserName()+";"+userBean.isVip());
  30. tv_Serializable.setText(bookBean.getBookName()+";"+bookBean.getBookPrice());
  31. }
  32. }

效果图

(2)保存对象的字节序列到本地文件中【使用Serializable】

  1. package com.why.project.androidcnblogsdemo.activity;
  2.  
  3. import android.content.Intent;
  4. import android.os.Bundle;
  5. import android.support.v7.app.AppCompatActivity;
  6. import android.view.View;
  7. import android.widget.TextView;
  8.  
  9. import com.why.project.androidcnblogsdemo.R;
  10. import com.why.project.androidcnblogsdemo.bean.BookBean;
  11. import com.why.project.androidcnblogsdemo.bean.UserBean;
  12.  
  13. import java.io.File;
  14. import java.io.FileInputStream;
  15. import java.io.FileOutputStream;
  16. import java.io.IOException;
  17. import java.io.ObjectInputStream;
  18. import java.io.ObjectOutputStream;
  19.  
  20. /**
  21. * Created by HaiyuKing
  22. * Used 序列化的首页界面
  23. */
  24.  
  25. public class SerializeOneActivity extends AppCompatActivity{
  26.  
  27. private UserBean mUserBean;
  28. private BookBean mBookBean;
  29.  
  30. @Override
  31. protected void onCreate(Bundle savedInstanceState) {
  32. super.onCreate(savedInstanceState);
  33. setContentView(R.layout.activity_serialize_one);
  34.  
  35. initDatas();
  36. initEvents();
  37.  
  38. }
  39.  
  40. private void initDatas() {
  41. mUserBean = new UserBean();
  42. mUserBean.setUserId(1111);
  43. mUserBean.setUserName("haiyuKing");
  44. mUserBean.setVip(true);
  45.  
  46. mBookBean = new BookBean();
  47. mBookBean.setBookName("Android开发艺术探索");
  48. mBookBean.setBookPrice(79f);
  49. }
  50.  
  51. private void initEvents() {
  52. findViewById(R.id.btn_intent).setOnClickListener(new View.OnClickListener() {
  53. @Override
  54. public void onClick(View view) {
  55.  
  56. }
  57. });
  58.  
  59. findViewById(R.id.btn_savefile).setOnClickListener(new View.OnClickListener() {
  60. @Override
  61. public void onClick(View view) {
  62. try {
  63. //文件存放的位置在 /data/data/<package>/files 下
  64. File file = new File(SerializeOneActivity.this.getFilesDir().getPath(), "cache.txt");
  65. ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
  66. out.writeObject(mBookBean);
  67. out.close();
  68. } catch (IOException e) {
  69. e.printStackTrace();
  70. }
  71.  
  72. }
  73. });
  74.  
  75. findViewById(R.id.btn_openfile).setOnClickListener(new View.OnClickListener() {
  76. @Override
  77. public void onClick(View view) {
  78. try {
  79. //文件存放的位置在 /data/data/<package>/files 下
  80. File file = new File(SerializeOneActivity.this.getFilesDir().getPath(), "cache.txt");
  81. ObjectInputStream out = new ObjectInputStream(new FileInputStream(file));
  82. BookBean newBookBean = (BookBean) out.readObject();//内容一致,但不是同一个对象
  83. out.close();
  84.  
  85. TextView tv_showbookInfo = findViewById(R.id.tv_showbookInfo);
  86. tv_showbookInfo.setText(newBookBean.getBookName()+";"+newBookBean.getBookPrice());
  87. } catch (IOException e) {
  88. e.printStackTrace();
  89. } catch (ClassNotFoundException e) {
  90. e.printStackTrace();
  91. }
  92.  
  93. }
  94. });
  95. }
  96.  
  97. }

cache.txt的路径:

效果图:

(3)将对象序列化后通过网络传输【使用Serializable】

暂时空缺

参考资料

序列化Serializable和Parcelable的理解和区别

《Android开发艺术探索》

Android中Parcelable接口用法

Android 读写文件 FileNotFoundException 异常

序列化Serializable和Parcelable的更多相关文章

  1. 转 序列化Serializable和Parcelable的区别详解

    什么是序列化,为什么要进行序列化 答:对象要进行传输(如:activity 与activity间 ,网络间 进程间等等).存储到本地就必须进行序列化 . 这种可传输的状态就是序列化. 怎么序列化??两 ...

  2. Android序列化之Serializable和Parcelable

    PS:还有几天就开学了.先来一发. 学习内容: 1.序列化的目的 2.Android中序列化的两种方式 3.Parcelable与Serializable的性能比较 4.Android中如何使用Par ...

  3. Android中Serializable和Parcelable序列化对象详解

    学习内容: 1.序列化的目的 2.Android中序列化的两种方式 3.Parcelable与Serializable的性能比较 4.Android中如何使用Parcelable进行序列化操作 5.P ...

  4. Serializable 和 Parcelable 区别

    http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0204/2410.html http://www.cnblogs.com/blu ...

  5. 浅谈Android中Serializable和Parcelable使用区别

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.概述 Android开发的时候,我们时长遇到传递对象的需求,但是我们无法将对象的引用传给Activity或者Fragment,我们需要将这些对象 ...

  6. Serializable 和 parcelable的实现和比较

    首先这个两个接口都是用来序列化对象的 但是两者在性能和应用场合上有区别,parcelable的性能更好,但是在需要保存或者网络传输的时候需要选择Serializable因为parcelable版本在不 ...

  7. Serializable和Parcelable的简单介绍

    Serializable和Pacelable接口可以完成对象的序列化过程,当我们需要通过Intent和Binder传输数据时就需要使用Parcelable或者Serializable. Seriali ...

  8. Intent传递对象——Serializable和Parcelable差别

    前两篇文章讨论了Serializable和Parcelable实现Intent之间传递对象和对象数组的方式.两种方法实现上相似,效果一致,怎么选择用哪种方法实现呢? Intent在不同的组件中传递对象 ...

  9. Serializable 和Parcelable 详解

    序列化:为了保存在内存中的各种对象的状态,并可以把保存的对象的状态读出来 安卓中实现序列化的接口有两个,一个是serializable,一个是parcelable. 一.实现序列化: 1.是可以将对象 ...

随机推荐

  1. spring-boot-starter-actouator2.1.4与c3p0版本0.9.1.2冲突

    报错前的pom文件: <?xml version="1.0" encoding="UTF-8"?><project xmlns="h ...

  2. <算法图解>读书笔记:第2章 选择排序

    第2章 选择排序 2.1 内存的工作原理 需要将数据存储到内存时,请求计算机提供存储空间,计算机会给一个存储地址.需要存储多项数据时,有两种基本方式-数组和链表 2.2 数组和链表 2.2.1 链表 ...

  3. 封装PDO函数

    funPDO.php <?php /** * @title: 封装PDO函数 * * @Features: * 1. 封装 SELECT ,INSERT,DELETE,UPDATE 操作 @do ...

  4. Windows本地代码仓库使用连接教程

    目录 软件安装 修改语言为中文 克隆远程仓库 文件上传教程 软件安装 安装Git(软件下载链接) 根据自己的系统选择对应版本下载安装 安装TortoiseGit(软件下载链接) 1.下载完毕解压文件夹 ...

  5. php |= 什么意思

  6. cookie设置域名问题,cookie跨域

    今天研究一天发现cookie无法设置除当前域名或者其父域名之外的其他domain. 这个是浏览器出于对cookie的保护造成的,也就是cookie无法跨域设置. 对于子域名也有如下规则,当前域名只能设 ...

  7. 20181115 python-第一章学习小结part2

    Python基本知识 变量,用来存储中间计算结果,在后面可进行调用被使用的东西,叫做变量. 变量的命名规则: 字母,数字,下划线组合 不能用数字开头 常见的关键字不能用啊 常量,不会变的量,称作常量. ...

  8. 安装selenium

    步骤: 1.下载setuptools2.点击安装setuptools.exe3.安装成功后,python的安装目录下会有Scripts的文件夹4.配置环境变量:python安装目录\Scripts5. ...

  9. java课程之团队开发冲刺阶段1.1

    一.今天所要完成的内容 1.实现软件添加日期的功能并生成当前所在周的功能 2.对之前的代码进行重新排版,将主函数的内容移到方法中 3.利用Android自带的左侧菜单栏实现app的整体美观

  10. node koa2 玩起来都是中间件啊

    玩的我想吐 !!! 整理下常用的中间件吧! 先列在这有空把这些中间件的使用技巧也写出来分享一下koa-router 路由中间件koa-bodyparser   POST数据处理的中间件koa-stri ...