什么是序列化

程序中存储和传递信息,需要有个合适的数据结构,最简单的是定义几个变量,变量多了之后再分门别类,便成了聚合若干变量的对象。代码在函数调用时可以直接传递对象,但更多的场合例如与文件交互、与网络交互、组件之间交互等等,就无法直接使用未经处理的对象。因此Java引入了序列化的概念,用于把一个对象转换为字节序列,然后再对这个字节序列做存储和传递操作。与之对应的是反序列化,反序列化是把一个字节序列恢复为Java对象的过程,而序列化是把Java对象转化为字节序列的过程。

Serializable

Serializable是Java设计用来定义序列化的接口,一个希望进行序列化的对象,需要实现Serializable接口。像上节《 Android开发笔记(二十六)Java的容器类》中介绍的Java容器类,从队列到映射,其实在各自的基类容器之外,也都实现了Serializable接口。也就是说,这些Java容器类其实都是可序列化的对象。另外,我们常见的变量类型如String、Integer等等,也实现了Serializable接口。既然这些对象都是可序列化的,那就可以把对象用IO写到文件里,之后再可以从文件里读出原对象,读出的变量值与之前的变量值是一样的。

实现简单的Serializable接口无需自己重写任何序列化函数,只要提供一个序列化版本的id(serialVersionUID),Java便会对这个对象进行高效的序列化操作。但由于Serializable方式使用了反射机制,使得序列化的过程相对较慢。并且,这种机制会在序列化的时候创建许多的临时对象,容易触发垃圾回收。

需要注意的是,Serializable序列化不保存静态变量,另外使用Transient关键字可声明对指定字段不做序列化。对于某些复杂的对象,也可以重写writeObject、readObject方法来自定义序列化过程,比如队列、映射这些容器类就重写了writeObject和readObject方法。

Parcelable

Parcelable的设计初衷,便是因为Serializable方式较耗资源且执行速度偏慢,为此Android设计了Parcelable用于组件之间的消息传递(包括线程间传递与进程间传递)。Parcelable数据仅在内存中存在,所以在内存间数据传输时推荐使用;而Serializable可将数据持久化方便保存,所以在需要保存文件或网络传输数据时应选择Serializable。

采用Parcelable方式的类,需要自己定义如何打包(写数据)和解包(读数据),其余的序列化操作则由底层实现。具体需要实现的方法如下:
writeToParcel(Parcel out, int flags) : 写数据
Parcelable.Creator<类名> CREATOR : 例行公事实现createFromParcel(读数据)和newArray
describeContents : 返回0即可

序列化对象的消息传递

下面是Serializable和Parcelable两种方式在Activity之间传递消息的代码例子。
Serializable对象代码

import java.io.Serializable;public class SerData implements Serializable {private static final long serialVersionUID = 999794470754667710L;public int mAge;public String mName;public boolean mMarried;public double mHeight;}

Parcelable对象代码

import android.os.Parcel;
import android.os.Parcelable;public class ParData implements Parcelable {public int mAge;public String mName;public boolean mMarried;public double mHeight;// 写数据@Overridepublic void writeToParcel(Parcel out, int flags) {out.writeInt(mAge);out.writeString(mName);out.writeByte((byte) (mMarried ? 1 : 0));out.writeDouble(mHeight);}// 例行公事实现createFromParcel和newArraypublic static final Parcelable.Creator<ParData> CREATOR= new Parcelable.Creator<ParData>() {// 读数据public ParData createFromParcel(Parcel in) {ParData par = new ParData();par.mAge = in.readInt();par.mName = in.readString();par.mMarried = in.readByte() != 0;par.mHeight = in.readDouble();return par;}public ParData[] newArray(int size) {return new ParData[size];}};@Overridepublic int describeContents() {return 0;}}

上面可以看到Parcelable暂不支持直接操作布尔boolean类型,但能间接通过设置byte位来实现boolean类型的参数传递。

主页面代码

import com.example.exmparcelable.data.ParData;
import com.example.exmparcelable.data.SerData;import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;public class MainActivity extends Activity implements OnClickListener {private EditText et_name, et_age, et_height;private Spinner sp_married;private String[] marriedStrArray = new String[]{"已婚", "未婚"};private boolean[] marriedBoolArray = new boolean[]{true, false};private boolean isMarried = true;private void setMarriedSpinner(Context context, int spinner_id, int seq) {sp_married = (Spinner) findViewById(spinner_id);ArrayAdapter<String> county_adapter;county_adapter = new ArrayAdapter<String>(context, R.layout.spinner_item, marriedStrArray);county_adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);// setPrompt是设置弹出对话框的标题sp_married.setPrompt("请选择婚否");sp_married.setAdapter(county_adapter);sp_married.setOnItemSelectedListener(new SpinnerSelectedListener());if (seq >= 0) {sp_married.setSelection(seq, true);} else {sp_married.setFocusable(false);}}class SpinnerSelectedListener implements OnItemSelectedListener {public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {isMarried = marriedBoolArray[arg2];}public void onNothingSelected(AdapterView<?> arg0) {}}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);et_name = (EditText) findViewById(R.id.et_name);et_age = (EditText) findViewById(R.id.et_age);et_height = (EditText) findViewById(R.id.et_height);setMarriedSpinner(this, R.id.sp_married, 0);Button btn_ser = (Button) findViewById(R.id.btn_ser);Button btn_par = (Button) findViewById(R.id.btn_par);btn_ser.setOnClickListener(this);btn_par.setOnClickListener(this);}@Overridepublic void onClick(View v) {if (et_age.getText()==null || et_age.getText().length()<=0) {Toast.makeText(this, "请输入年龄", Toast.LENGTH_LONG).show();return;} else if (et_name.getText()==null || et_name.getText().length()<=0) {Toast.makeText(this, "请输入姓名", Toast.LENGTH_LONG).show();return;} else if (et_height.getText()==null || et_height.getText().length()<=0) {Toast.makeText(this, "请输入身高", Toast.LENGTH_LONG).show();return;}if (v.getId() == R.id.btn_ser) {SerData ser = new SerData();ser.mAge = Integer.parseInt(et_age.getText().toString());ser.mName = et_name.getText().toString();ser.mMarried = isMarried;ser.mHeight = Double.parseDouble(et_height.getText().toString());Intent intent = new Intent(this, SerializableActivity.class);Bundle bundle = new Bundle();bundle.putSerializable("ser", ser);intent.putExtras(bundle);startActivity(intent);} else if (v.getId() == R.id.btn_par) {ParData par = new ParData();par.mAge = Integer.parseInt(et_age.getText().toString());par.mName = et_name.getText().toString();par.mMarried = isMarried;par.mHeight = Double.parseDouble(et_height.getText().toString());Intent intent = new Intent(this, ParcelableActivity.class);Bundle bundle = new Bundle();bundle.putParcelable("par", par);intent.putExtras(bundle);startActivity(intent);}}}

Serializable页面代码

import com.example.exmparcelable.data.SerData;import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.widget.TextView;public class SerializableActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_ser);Bundle bundle = getIntent().getExtras();SerData ser = (SerData) bundle.getSerializable("ser");String desc = String.format("您输入的人物信息是:姓名%s,年龄%d,身高%f,婚否%b", ser.mName, ser.mAge, ser.mHeight, ser.mMarried);TextView tv_ser = (TextView) findViewById(R.id.tv_ser);tv_ser.setText(desc);}}

Parcelable页面代码

import com.example.exmparcelable.data.ParData;import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.widget.TextView;public class ParcelableActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_par);Bundle bundle = getIntent().getExtras();ParData par = bundle.getParcelable("par");String desc = String.format("您输入的人物信息是:姓名%s,年龄%d,身高%f,婚否%b", par.mName, par.mAge, par.mHeight, par.mMarried);TextView tv_par = (TextView) findViewById(R.id.tv_par);tv_par.setText(desc);}}

点击下载本文用到的对象序列化的工程代码

点此查看Android开发笔记的完整目录

Android开发笔记(二十七)对象序列化相关推荐

  1. 【Visual C++】游戏开发笔记二十七 Direct3D 11入门级知识介绍

    游戏开发笔记二十七 Direct3D 11入门级知识介绍 作者:毛星云    邮箱: happylifemxy@163.com    期待着与志同道合的朋友们相互交流 上一节里我们介绍了在迈入Dire ...

  2. Android开发笔记(十七)GIF动画的实现GifAnimation

    GIF在Windows上是常见的图片格式,主要用来播放短小的动画.但在手机上由于系统资源紧张,所以Android并没有直接支持GIF格式,如果在ImageView中放入一张gif文件,你会发现显示出来 ...

  3. 【Visual C++】游戏开发笔记二十七 Direct3D 11入门级知识介绍

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. http://blog.csdn.net/zhmxy555/article/details/7707628 作者:毛星云 邮箱: happ ...

  4. Andriod开发之二十:Android开发笔记(序)写在前面的目录

    https://blog.csdn.net/aqi00/article/details/50038385 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教 ...

  5. Android开发笔记(序)写在前面的目录

    知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教训,与网友互相切磋,从而去芜存菁进一步提升自己的水平.因此博主就想,入门的东西咱就不写了,人不能老停留在入 ...

  6. Android开发笔记(序)

    本开发笔记,借鉴与其他开发者整理的文章范例与心得体会.在这里作为开发过程中的一个总结与笔记式记录. 如有侵犯作者权益,请及时联系告知删除.俗话说:集百家成一言,去粕成金. ************** ...

  7. Android开发笔记(序)写在前面的目录大全

    转自  湖前琴亭 的博客https://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面 ...

  8. Android开发笔记(一百二十七)活用提示窗Toast和Snackbar

    提示窗Toast 大家平时都经常用Toast,可是你是否发现,系统默认的Toast样式太过单调乏味呢?其实Toast的界面也允许开发者自行定制,只要定义好提示窗的布局文件,即可调用Toast类的set ...

  9. Android开发笔记(一百二十六)自定义音乐播放器

    MediaRecorder/MediaPlayer 在Android手机上面,音频的处理比视频还要复杂,这真是出人意料.在前面的博文< Android开发笔记(五十七)录像录音与播放>中, ...

最新文章

  1. ORACLE 数据的逻辑组成
  2. etc下没有mysql_我在linux下,安装mysql的时候,cp support-files/my-medium.cnf /etc/my.cnf找不到my-medium.cnf...
  3. Python中递增和递减运算符的行为
  4. gradle 项目运行主类报错
  5. JavaScript基础一
  6. protobuf相关:反射、rmi
  7. 使用Null Object设计模式[转]
  8. cobbler基础安装
  9. 关于代码效率提升的方法心路历程(购物车)
  10. 车厢调度(信息学奥赛一本通-T1357)
  11. Android NDK: 如何编译JNI为指定的指令集(armeabi/arm64)
  12. C# excel导入导出,NOPI ,简单例子
  13. 电场在计算机专业的应用,电磁学在电力系统中的应用
  14. 解决Fedora14使用root权限登录问题
  15. Hive报错记录——林子雨教材
  16. 对大数据 数据挖掘和机器学习的认识和理解
  17. matlab中grid相关知识
  18. 层次分析法详解(matlab)
  19. Java中进行Debug断点调试
  20. 回忆2016:心怀梦想,奋力前行

热门文章

  1. Hexo中Next主题个性化美化的解决方案
  2. Hadoop环境的配置搭建和基本概念
  3. 解决忽略vscode中pylint报错的问题
  4. 一文了解Innodb中的锁
  5. SQL Server 当表分区遇上唯一约束(转载)
  6. excel 汇总 mysql_利用mysql收集excel录入汇总
  7. [Ext JS]5.8 Group Grid-分组网格
  8. [过年菜谱之]千张春笋蒸酱鸭
  9. [设计模式-结构型]装饰模式(Decorator)
  10. html无法显示null打开,js出现null错误的原因?