对于Android来说传递复杂类型,主要是将自己的类转换为基础的字节数组,Activity之间传递数据是通过Intent实现的。 Android序列化对象主要有两种方法,实现Serializable接口、或者实现Parcelable接口。实现Serializable接口是JavaSE本身就支持的,而Parcelable是Android特有的功能,效率比实现Serializable接口高,而且还可以用在进程间通信(IPC)中。实现Serializable接口非常简单,声明一下就可以了。而实现Parcelable接口稍微复杂一些,但效率更高,推荐用这种方法提高性能。
Parcel 在英文中有两个意思,其一是名词,为包裹,小包的意思; 其二为动词,意为打包,扎包。邮寄快递中的包裹也用的是这个词。Android采用这个词来表示封装消息数据。这个是通过IBinder通信的消息的载体。需要明确的是Parcel用来存放数据的是内存(RAM),而不是永久性介质(Nand等)。
Parcelable,定义了将数据写入Parcel,和从Parcel中读出的接口。一个实体(用类来表示),如果需要封装到消息中去,就必须实现这一接口,实现了这一接口,该实体就成为“可打包的”了。
Parcelable接口的作用:实现了Parcelable接口的实例可以将自身的状态信息(状态信息通常指的是各成员变量的值)写入Parcel,也可以从Parcel中恢复其状态。Parcel用来完成数据的序列化传递。下面就介绍一下实现Parcelable接口的方法。
通过实现Parcelable接口序列化对象的步骤:
1. 实现Parcelable接口。
2. 实现Parcelable接口的public void writeToParcel(Parcel dest, int flags)方法 。
3. 自定义类型中必须含有一个名称为CREATOR的静态成员,该成员对象要求实现Parcelable.Creator接口及其方法。
简而言之:通过writeToParcel将你的对象映射成Parcel对象,再通过createFromParcel将Parcel对象映射成你的对象。也可以将Parcel看成是一个流,通过writeToParcel把对象写到流里面,在通过createFromParcel从流里读取对象,只不过这个过程需要你来实现,因此写的顺序和读的顺序必须一致。
在实现Parcelable的实现中,规定了必须定义一个静态成员, 初始化为嵌入接口的实现类。
Intent 可以携带对象来在不同的Activity中传递数据,要传递的数据必须实现三个方法
1. describeContents()返回0就可以
2. writeToParcel(Parcel parcel, int flag) 把需要写入的数据写入Parcel中,然后框架调用此方法发送给接收端的Activity
3. public static final Parcelable.Creator<ParcelableObject> CREATOR 外部类反序列化该类时调用此方法
一定要注意:写入parcel和反序列化parcel时顺序一定要相同,不然数据会出错。
案例介绍:
/**
* ParcelableObject.java
* com.androidtest.parcelable
*
* Function: TODO
*
* ver date author
* ──────────────────────────────────
* 2011-5-11 Leon
*
* Copyright (c) 2011, TNT All Rights Reserved.
*/
package com.androidtest.parcelable;
import android.os.Parcel;
import android.os.Parcelable;
/**
* ClassName:ParcelableObject 需要实现三个方法,describeContents()返回0就可以 、 writeToParcel(Parcel parcel, int flag)
* 写入Parcel和public static final Parcelable.Creator
<parcelableobject><span style="font-size: 14px"> CREATOR 供外部类反序列化该类
* 一定要注意顺序后面这个两个函数读和写的顺序要相同,不然数据会出错
* Function: TODO
* Reason: TODO ADD REASON
*
* @author Leon
* @version
* @since Ver 1.1
* @Date 2011-5-11
*/
public class ParcelableObject implements Parcelable{
private String name ;
private String surName ;
private int age ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurName() {
return surName;
}
public void setSurName(String surName) {
this.surName = surName;
}
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 flag) {
// TODO Auto-generated method stub
dest.writeInt(age);
dest.writeString(name);
dest.writeString(surName);
}
public static final Parcelable.Creator CREATOR = new Creator() {
@Override
public ParcelableObject createFromParcel(Parcel source) {
// TODO Auto-generated method stub
ParcelableObject parcelableObj = new ParcelableObject();
parcelableObj.age=source.readInt();
parcelableObj.surName=source.readString();
parcelableObj.name = source.readString();
return parcelableObj;
}
@Override
public ParcelableObject[] newArray(int size) {
// TODO Auto-generated method stub
return new ParcelableObject[size];
}
};
}
ParcelableActivity1 发送的代码:
package com.androidtest.parcelable;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
public class ParcelableActivity1 extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
LinearLayout linearLayout = new LinearLayout(this);
Button button = new Button(this);
button.setText("Send Parcelable Object");
linearLayout.addView(button);
button.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0) {
ParcelableObject passObject = new ParcelableObject();
passObject.setName("Leon Zhang");
passObject.setAge(18);
passObject.setSurName("xxx");
Intent intent = new Intent(ParcelableActivity1.this,ParcelableActivity2.class);
// 使用Bundle发送
// Bundle bundle = new Bundle();
// bundle.putParcelable("key", passObject);
intent.putExtra("key", passObject);
// intent.putExtras(bundle);
intent.putExtra("key2", "out of bundle");
startActivity(intent);
}
});
this.setContentView(linearLayout);
}
}
ParcelableActivity2 接收的代码:
package com.androidtest.parcelable;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class ParcelableActivity2 extends Activity {
private static final String TAG = ParcelableActivity2.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
ParcelableObject passObject = this.getIntent()
.getParcelableExtra("key");
Log.v(TAG, "Name: " + passObject.getName() + " Surname: "
+ passObject.getSurName() + " Age: "
+ String.valueOf(passObject.getAge())
+ " out of bundle is :"
+ this.getIntent().getStringExtra("key2"));
Bundle myBundle = this.getIntent().getExtras();
Log.v(TAG,"XX: "
+ ((ParcelableObject) myBundle.getParcelable("key"))
.getName()+ " Key2 :"+ myBundle.getString("key2"));
}
}
经过测试发现,当使用Intent传递数据时,如果你自己创建了一个Bundle,则无论要传的数据是否放入Bundle(如直接intent.putExtra("xx" , "xx")),都会放到放到此Bundle中。如果没有创建此Bundle,则会默认创建一个Bundle来存放数据。当取数据时可以先取Bundle再从Bundle中取数据,或者直接取就好了。
参考:
http://zuiniuwang.blog.51cto.com/3709988/718330