对于写代码而言,使用Intent在Activity之间传递对象,最简单的方式就是使被传递对象的类实现Serializable
空接口。
Serializable
并非Android定义的接口,而是java.io中定义的。
import java.io.Serializable;
public class Person implements Serializable {
private String name;
private double height;
public void setName(String name) {
this.name=name;
}
public void setHeight(double height) {
this.height=height;
}
public String getName() {
return name;
}
public double getHeight() {
return height;
}
}
要注意的是使用Serializable
接口必须事先导入java.io.Serializable
。
Person person=new Person();
person.name="Lishaoyin";
person.height="1.70";
Intent intent=new Intent(this,TargetActivity.class);
intent.putExtra("Lishaoyin",person);
startActivity(intent);
说明:此时用到的putExtra()
的版本为:
public Intent putExtra(String name,Serializable value)
特别注意:若被传递对象引用了其它类的对象,被引用对象的类也必须实现Serializable
接口!
CurrentActivity.java
import...
import java.io.Serializable
public class CurrentActivity extends Activity
implements View.OnClickListener {
private Person person=new Person();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//load currentActivity.xml
setContentView(R.layout.currentActivity);
Button btn_1=(Button)findviewById(R.id.btn_1);
btn_1.setOnClickListener(this);
person.setName("Lishaoyin");
person.setHeight(1.70);
}
@Override
protected onClick(View v) {
Intent intent=new Intent(this,TargetActivity.class);
intent.putExtra("Lishaoyin",person);
startActivity(intent); //launch TargetActivity
}
}
Person.java
//implements Serializable interface
public class Person implements Serializable {
private String name;
private double height;
public void setName(String name) {
this.name=name;
}
public void setHeight(double height) {
this.height=height;
}
public String getName() {
return name;
}
public double getHeight() {
return height;
}
}
import...
import java.io.Serializable;
Intent intent=getIntent();
Person person=
(Person)intent.getSerializableExtra("Lishaoyin");
注意,这里使用的是getSerializableExtra()
方法获取传来的对象,它的定义为:
public Serializable getSerializableExtra(String name)
它的返回值是Serializable
类型,所以要使用它得到的对象,必须对其进行强制类型转换。
import...
import java.io.Serializable;
public class TargetActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//load targetActivity.xml
setContentView(R.layout.targetActivity);
Intent intent=getIntent();
Person person=
(Person)intent.getSerializableExtra("Lishaoyin");
Toast.makeText(this,person.getName(),LENGTH_SHORT).show();
}
}
Parcelable
接口定义在Parcelable.java
中,是Android专用于传递对象的接口。跟Serializable
接口一样,若被传递对象引用了其它类的对象,被引用对象的类也必须实现Parcelable
接口。
1.实现describeContents()
方法,一般直接return 0
即可。
@Override
public int describeContents() {
return 0; //directly return 0 generally
}
2.实现writeToParcel()
方法,在这个方法中将被传递对象中所有需要用到的字段都写入Parcel容器从而将对象数据序列化,而不需要的可以不写入。
public void writeToParcel(Parcel dest,int flags) {
dest.writeString(name);
dest.writeDouble(height);
dest.writeInt(weight);
}
这个方法中使用writeXXX()
来向Parcel容器写入基本数据类型以及String
类型,需要注意的是没有直接序列化boolean
类型的方法,即writeBoolean()
是不存在的。如果需要使用boolean
类型,就要用其它方式间接实现。
3.创建Creator>
的实例CREATOR
,并且重写其中的两个方法。
public static final Creator<?> CREATOR=new Creator<Person>() {
@Override
public Person createFromParcel(Parcel source) {
Person person=new Person();
person.name=source.readString();
person.height=source.readDouble();
person.weight=source.readInt();
return person;
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
}; //don't forget ";"
Creator>
是一个泛型接口,其中的>
表示自动适配类型参数,在上例中创建CREATOR
实例时它自动适配Person
类。
重写createFromParcel()
中,使用readXXX()
方法将对象数据反序列化。特别注意:反序化顺序要与序列化顺序一致,否则将导致数据错乱。例如之前先序列化name
,再序列化height
最后序列化weight
,那么反序列化也必须先反序列化name
,再反序列化height
,最后反序列化weight
。
重写newArray()
方法中,一般直接返回new Person[size]
即可。
4.使用putExtra()
方法传递对象并开启目标Activity。
Person person=new Person();
person.setPerson("Tony Stark",1.78,70);
Intent intent=new Intent();
intent.setClass(this,TargetActivity.class);
intent.putExtra("Tony",person);
startActivity(intent);
此时用到的putExtra()
的版本为:
public Intent putExtra(String name,Parcelable value)
实现Parcelable
接口方式传递对象看上去很复杂难懂,但实际上可以把这个过程视为一个模板,AndroidStudio会自动产生最关键的代码,其余自定义部分自由发挥即可。
Person.java
import...
public class Person implements Parcelable {
private String name;
private double height;
private int weight;
public void setPerson(String name,double height,int weight) {
this.name=name;
this.height=height;
this.weight=weight;
}
public String getName() {
return name;
}
public double getHeight() {
return height;
}
public int getWeight() {
return weight;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest,int flags) {
dest.writeString(name);
dest.writeDouble(height);
dest.writeInt(weight);
}
public static final Creator<?> CREATOR=new Creator<Person>() {
@Override
public Person createFromParcel(Parcel source) {
Person person=new Person();
person.name=source.readString();
person.height=source.readDouble();
person.weight=source.readInt();
return person;
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
}; //don't forget ";"
}
CurrentActivity.java
import...
public class CurrentActivity extends Activity
implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//load currentActivity.xml
setContentView(R.layout.currentActivity);
Button btn_1=(Button)findviewById(R.id.btn_1);
btn_1.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Person person=new Person();
person.setPerson("Tony Stark",1.78,70);
Intent intent=Intent(this,TargetActivity.class);
intent.putExtra("Tony",person);
startActivity(intent);
}
}
Intent intent=getIntent();
Person person=(Person)intent.getParcelableExtra("Tony");
使用getParcelableExtra()
方法,注意进行强制类型转换。
TargetActivity.java
import...
public class TargetActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//load targetActivity.xml
setContentView(R.layout.targetActivity);
TextView tv_1=(TextView)findviewById(R.id.tv_1);
TextView tv_2=(TextView)findviewById(R.id.tv_2);
TextView tv_3=(TextView)findviewById(R.id.tv_3);
Intent intent=getIntent();
Person person=(Person)intent.getParcelableExtra("Tony");
tv_1.setText("姓名:"+person.getName());
tv_2.setText("身高:"+person.getHeight());
tv_3.setText("体重:"+person.getWeight());
}
}
两者都有序列化和反序列化操作。
1.存储媒介:Serializable
将对象转化为二进制文件,使用IO读写存储在外部存储设备上。Parcelable
将对象存储在内存上,直接在内存上进行数据读写。
2.读写速度:由于Parcelable
直接在内存上进行数据读写,所以Parcelable
的读写速度更快。
3.存储保持:Serializable
将对象存储在外部设备上,所以使用Serializable
可以持久保存对象的当前状态。Parcelable
将对象存储在内存上,所以每次重启程序都将丢失对象状态。
3.用途场合:Serializable
将对象转换成二进制文件,所以可以用于进程之间传递对象、程序向外部存储设备传递对象、程序向网络传递对象。Parcelable
用于不需要持久保存对象状态的传递对象场合。
一般情况下,在Activity之间传递对象不需要持久保存对象状态,所以考虑性能,优先使用Parcelable
。
比较类型 | Serializable | Parcelable |
---|---|---|
存储媒介 | 外部存储设备 | 内存 |
读写速度 | 一般 | 较快 |
存储保持 | 持久存储 | 暂时存储 |