前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发笔记(二十七)对象序列化

Android开发笔记(二十七)对象序列化

作者头像
aqi00
发布2019-01-18 10:43:24
6270
发布2019-01-18 10:43:24
举报
文章被收录于专栏:老欧说安卓

什么是序列化

程序中存储和传递信息,需要有个合适的数据结构,最简单的是定义几个变量,变量多了之后再分门别类,便成了聚合若干变量的对象。代码在函数调用时可以直接传递对象,但更多的场合例如与文件交互、与网络交互、组件之间交互等等,就无法直接使用未经处理的对象。因此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对象代码

代码语言:javascript
复制
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对象代码

代码语言:javascript
复制
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;

    // 写数据
    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mAge);
        out.writeString(mName);
        out.writeByte((byte) (mMarried ? 1 : 0));
        out.writeDouble(mHeight);
    }

    // 例行公事实现createFromParcel和newArray
    public 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];
        }
    };
    
	@Override
	public int describeContents() {
		return 0;
	}

}

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

代码语言:javascript
复制
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) {
		}
	}
	
	@Override
	protected 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);
	}

	@Override
	public 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页面代码

代码语言:javascript
复制
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 {

	@Override
	protected 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页面代码

代码语言:javascript
复制
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 {

	@Override
	protected 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开发笔记的完整目录

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015年12月25日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是序列化
  • Serializable
  • Parcelable
  • 序列化对象的消息传递
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档