安卓Android Intent 传递对象objet
安卓开发中,最常遇到的问题之一——不同的activity之间传值或者传递对象。
1 传值
通常,传递值(字符串,数字等)比较简单。
我们去粗取精,挑重点讲:
btn_next_activity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent myIntent = new Intent(MainActivity.this, Activity2.class);
myIntent.putExtra("data", selectedString);
startActivity(myIntent);
}
});
通过这段对应按钮的跳转监听可以看到,只需要在跳转时,让intent绑定数据, putExtra使用键值对:
myIntent.putExtra("data", selectedString);
然后在接收的Activity/目标Activity中接受一下这个传过来的值:
//通过Activity.getIntent()获取当前页面接收到的Intent。
Intent intent =getIntent();
//getXxxExtra方法获取Intent传递过来的数据
String data_selected_string =intent.getStringExtra("data");
我们就把传过来的值放在 data_selected_string里面了,想要怎么操作就随便了~
2 传递对象
但如果要传递一个对象(包含的信息更复杂),需要先将它序列化Serializable 或者 打包Parcelable.
- 类实现 Serializable,Java 提供的序列化的接口
- 类实现 Parcelable,Android提供的在移动端的序列化接口,效率更高
Serializable (简单)
这俩差不多,首先我们挑简单的来实现,使用Serializable。我们按步骤说:
1. 在要传递的对象的类上加上 implements Serializable (或 Parcelable):
public class Planet implements Serializable {
private String nom;
private double distance_ua;
private double rayon_km;
private double masse;
...
2. 在要Intent传递传递时使用Serializable序列化对象 :
btn_next_activity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent myIntent = new Intent(MainActivity.this, Activity3.class);
myIntent.putExtra("Choose planet:", (Serializable) selectedPlanet);
// myIntent.putExtra("data", (Parcelable) selectedPlanet);
startActivity(myIntent);
}
});
3. 在目标Activity接收(使用intent.getSerializableExtra):
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_3);
Intent intent = getIntent();
Planet selectedPlanet = (Planet) intent.getSerializableExtra("Choose planet:");
// Planet selectedPlanet = intent.getParcelableExtra("Choose planet:");
恭喜!这就OK啦!
Parcelable (效率高)
Parcelable 稍微复杂一点,需要写包,读包。不过实际写起来,也比较简单:
1. 在要传递的对象的类上加上 implements Parcelable, 代码会提示引入相关的方法 :
public class Planet implements Parcelable {
private String nom;
private double distance_ua;
private double rayon_km;
private double masse;
public Planet(String nom, double distance_ua, double rayon_km, double masse) {
this.nom = nom;
this.distance_ua = distance_ua;
this.rayon_km = rayon_km;
this.masse = masse;
}
protected Planet(Parcel in) {
nom = in.readString();
distance_ua = in.readDouble();
rayon_km = in.readDouble();
masse = in.readDouble();
}
public static final Creator<Planet> CREATOR = new Creator<Planet>() {
@Override
public Planet createFromParcel(Parcel in) {
return new Planet(in);
}
@Override
public Planet[] newArray(int size) {
return new Planet[size];
}
};
//... 中间有一些 getter() setter()方法略
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(nom);
dest.writeDouble(distance_ua);
dest.writeDouble(rayon_km);
dest.writeDouble(masse);
}
}
2. 在要Intent传递传递时使用Parcelable序列化对象 :
和前面Serializable没有太大区别
btnGo4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent myIntent = new Intent(MainActivity.this, Activity4.class);
myIntent.putExtra("data", selectedPlanet);
startActivity(myIntent);
}
});
3. 在目标Activity接收(使用intent.getSerializableExtra):
和前面Serializable没有太大区别
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_4);
Intent intent = getIntent();
// Planet2 selectedPlanet = (Planet2) intent.getSerializableExtra("Choose planet:");
Planet selectedPlanet = intent.getParcelableExtra("data");
txtView_selected_planet2 = findViewById(R.id.txt_selected_planet_2);
txtView_selected_planet2.setText(selectedPlanet.getNom()+
"\n"+selectedPlanet.getDistance_ua()+
"\n"+selectedPlanet.getRayon_km()+
"\n"+selectedPlanet.getMasse());
}
3. Serializable / Parcelable 作用、区别、效率对比及选择
3.1 作用
Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。而Android的Parcelable的设计初衷是因为Serializable效率过慢,为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable是通过IBinder通信的消息的载体。
从上面的设计上我们就可以看出优劣了。
3.2 效率及选择
Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如activity间传输数据,而Serializable可将数据持久化方便保存,所以在需要保存或网络传输数据时选择Serializable,因为android不同版本Parcelable可能不同,所以不推荐使用Parcelable进行数据持久化
3.3 编程实现
对于Serializable,类只需要实现Serializable接口,并提供一个序列化版本id(serialVersionUID)即可。而Parcelable则需要实现writeToParcel、describeContents函数以及静态的CREATOR变量,实际上就是将如何打包和解包的工作自己来定义,而序列化的这些操作完全由底层实现 (实际上,简单的传递,使用默认即可,不必重写,重写是根据自己的需要定制,提供了更多的选择性)
参考:
https://juejin.im/entry/58abec895c497d005f72b9f3
https://blog.csdn.net/yzzst/article/details/26255611 (对比)