在编程中只要提到对象的序列化,我想大多数做过开发的同胞都会想到Serializable这个接口,这是JavaSE中支持的一种对象序列化方式,在Android中提供了另外一个对象序列化的接口,那就是今天我想阐述的重点内容Parcelable。
序列化的原因:
1.可以永久性的保持对象到本地磁盘中
2.作为数据流通过网络进行传输
3.可以实现进程之间的通讯
一 、Serializable接口
Serializable接口它没有任何方法和属性的接口,就是一个标识的作用,表示实现了该接口的对象可以进行序列化。
二、Parcelable接口
Parcelabe接口是Android特有的接口,实现这个接口要比Serializable接口复杂一些,该接口需要实现writeToParcel()和describeContents()方法,还要实例化静态内部对象CREATOR实现接口Parcelabe.Creator。
三、Parcelabe和Serializable的作用、效率、区别和选择
1、作用:
Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以便数据传输,当然这种传输可能是程序内部的也可以是两个不同程序之间的。而Android提供的Parcelable的设计初衷是因为Serializable效率太慢,为了让Android程序内的不同组件之间以及不同Android程序之间高效的传输数据而设计,这些数据仅存在于内存中。Parcelable是通过IBinder通信的消息载体。
2、效率及其选择:
Parcelable的性能比Serializable好,在内存开销方面小,所以在内存之间传输数据时推荐使用Parcelable,比如Activity之间传输数据,而Serializable可以将数据持久化方便保存,所以在需要保存或网络传输时应该选择Serializable,因为Android不同版本的Parcelable有可能不同,所以不推荐使用Parcelable进行数据持久化。
四、演示Demo
package com.test.mode;
import android.os.Parcel;
import android.os.Parcelable;
public class StudentInfo implements Parcelable {
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;
}
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeString(name);
dest.writeInt(age);
}
public static final Parcelable.Creator<StudentInfo> CREATOR = new Creator<StudentInfo>() {
@Override
public StudentInfo[] newArray(int size) {
// TODO Auto-generated method stub
return new StudentInfo[size];
}
@Override
public StudentInfo createFromParcel(Parcel source) {
// TODO Auto-generated method stub
StudentInfo stu = new StudentInfo();
stu.name = source.readString();
stu.age = source.readInt();
return stu;
}
};
}
注意:实例化静态内部对象CREATOR实现接口Parcelabe.Creator时,必须用public static final 进行修饰,并且CREATOR只能为这个名字,不能更改,并且名字必须大写。
实现CREATOR对象中的createFromParcel()和newArray()方法,将Parcel对象反序列化成你定义的对象。
如下Demo演示了从OneActivity界面向TwoActivity界面传递一个ArrayList集合,然后在TwoActivity中打印出获取到的集合数据。
OneActivity代码:
public class OneActivity extends Activity implements OnClickListener {
private ArrayList<StudentInfo> list;
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.one);
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(this);
list = getData();
}
private ArrayList<StudentInfo> getData() {
ArrayList<StudentInfo> list = new ArrayList<StudentInfo>();
StudentInfo stu1 = new StudentInfo("scott", 23);
StudentInfo stu2 = new StudentInfo("zhangsan", 18);
StudentInfo stu3 = new StudentInfo("lishi", 20);
list.add(stu1);
list.add(stu2);
list.add(stu3);
return list;
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.btn:
Intent intent = new Intent(this, TwoActivity.class);
System.out.println("-----点击了btn");
intent.putExtra("students", list);
startActivity(intent);
break;
default:
break;
}
}
}
TwoActivity代码:
public class TwoActivity extends Activity {
private ArrayList<StudentInfo> list;
private TextView tv_show;
private StringBuffer sb = new StringBuffer();
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.two);
tv_show = (TextView) findViewById(R.id.tv_show);
System.out.println("执行了OneActivity的onCreate()方法!");
list = getIntent().getParcelableArrayListExtra("students");
for (int i = 0; i < list.size(); i++) {
sb.append(list.get(i).toString() + "\n");
System.out.println("student=" + list.get(i).toString());
}
tv_show.setText(sb.toString());
}
}
日志打印结果:
04-02 19:35:24.671: I/System.out(10549): -----点击了btn
04-02 19:35:24.671: I/System.out(10549): 执行了Parcelable接口的writeToParcel()方法!
04-02 19:35:24.672: I/System.out(10549): 执行了Parcelable接口的writeToParcel()方法!
04-02 19:35:24.672: I/System.out(10549): 执行了Parcelable接口的writeToParcel()方法!
04-02 19:35:24.842: I/System.out(10549): 执行了OneActivity的onCreate()方法!
04-02 19:35:24.843: I/System.out(10549): 执行了CREATOR对象中的createFromParcel()方法,stu=StudentInfo [name=scott, age=23]
04-02 19:35:24.843: I/System.out(10549): 执行了CREATOR对象中的createFromParcel()方法,stu=StudentInfo [name=zhangsan, age=18]
04-02 19:35:24.843: I/System.out(10549): 执行了CREATOR对象中的createFromParcel()方法,stu=StudentInfo [name=lishi, age=20]
04-02 19:35:24.843: I/System.out(10549): student=StudentInfo [name=scott, age=23]
04-02 19:35:24.843: I/System.out(10549): student=StudentInfo [name=zhangsan, age=18]
04-02 19:35:24.844: I/System.out(10549): student=StudentInfo [name=lishi, age=20]
根据打印的日子可以看出,当执行putExtra()方法的时候,系统会自动调用Parcelable接口的writeToParcel()方法将数据写入内存或磁盘中,这就是Android中的序列化。当程序执行 getIntent().getParcelableArrayListExtra("students")方法的时候,系统会调用CREATOR对象中的createFromParcel()方法,将序列化到内存或磁盘中的数据反序列化成对象。其实 createFromParcel(Parcel source) 方法的形参source和Parcelable中writeToParcel(Parcel dest, int flags)方法的形参dest是同一个对象。