android.os.Parcelable
对于Android来说传递复杂类型,主要是将自己的类转换为基础的字节数组,Activity之间传递数据是通过Intent实现的。 Android序列化对象主要有两种方法,实现Serializable接口、或者实现Parcelable接口。实现Serializable接口是Java SE本身就支持的,而Parcelable是Android特有的功能,效率比实现Serializable接口高,而且还可以用在进程间通信(IPC)中。实现Serializable接口非常简单,声明一下就可以了。而实现Parcelable接口稍微复杂一些,但效率更高,推荐用这种方法提高性能。
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实现要点:需要实现三个东西
1)writeToParcel 方法。该方法将类的数据写入外部提供的Parcel中.声明如下:
writeToParcel (Parcel dest, int flags) 具体参数含义见javadoc
2)describeContents方法。没搞懂有什么用,反正直接返回0也可以
3)静态的Parcelable.Creator接口,本接口有两个方法:
createFromParcel(Parcel in) 实现从in中创建出类的实例的功能 newArray(int size) 创建一个类型为T,长度为size的数组,仅一句话(return new T[size])即可。估计本方法是供外部类反序列化本类数组使用。
eg:
public class MyParcelable implements Parcelable { private int mData; public int describeContents() { return 0; } public void writeToParcel(Parcel out, int flags) { out.writeInt(mData); } public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>() { public MyParcelable createFromParcel(Parcel in) { return new MyParcelable(in); } public MyParcelable[] newArray(int size) { return new MyParcelable[size]; } }; private MyParcelable(Parcel in) { mData = in.readInt(); } }
序列化原因:
1.永久性保存对象,保存对象的字节序列到本地文件中;
2.通过序列化对象在网络中传递对象;
3.通过序列化在进程间传递对象。
至于选取哪种可参考下面的原则:
1.在使用内存的时候,Parcelable 类比Serializable性能高,所以推荐使用Parcelable类。
2.Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
3.Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点, 也不提倡用,但在这种情况下,还是建议你用Serializable 。
作用
android提供了一种新的类型:Parcel。本类被用作封装数据的容器,封装后的数据可以通过Intent或IPC传递。 除了基本类型以外,只有实现了Parcelable接口的类才能被放入Parcel中。
而对于Intent还有Bundle,他们只能携带的数据有八种基本类型,还有String,其实String实现了Serializable,即还有实现接口Serializable或者Parcelable类型的类都可以。否则,当数据过多时,需要用一个类(结构)封装数据,该类需要实现Serializable或者Parcelable。
既可以通过以下方法进行数据封装:
Intent:
intent.putExtra(String name, Serializable value)
intent.putExtra(String name, Parcelable value)
intent.putExtra(String name, Parcelable[] value)
intent.putParcelableArrayListExtra(String name, ArrayList<? extends Parcelable> value)
intent.getSerializableExtra(name)
intent.getParcelableArrayExtra(name)
intent.getParcelableArrayListExtra(name)
intent.getParcelableExtra(name)
Bundle:
data.putSerializable(key, value)
data.putParcelable(key, value)
data.putParcelableArray(key, value)
data.putParcelableArrayList(key, value)
data.getSerializable(key)
data.getParcelable(key)
data.getParcelableArray(key)
data.getParcelableArrayList(key)
一个例子:
MainActivity.java
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = getIntent();//可以直接获取INtent,为何还要new Intent???
Person p = new Person();
p.map = new HashMap<String, String>();
p.map.put("yes", "ido");
p.name = "ok";
intent.putExtra("yes", p);
intent.setClass(this, Test.class);
startActivity(intent);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Test.java
public class Test extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
Intent i = getIntent();
Person p = i.getParcelableExtra("yes");
Log.d("nimeimei", "name=" + p.name + "," + "size=" + p.map.size());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.test, menu);
return true;
}
}
Person.java
public class Person implements Parcelable {
public HashMap<String, String> map = new HashMap<String, String>();
public String name;
@Override
public int describeContents() {
Log.d("nimeimei", "0000000000000000describeContents");
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
Log.d("nimeimei", "111111111111111111111111111writeToParcel");
dest.writeMap(map);
dest.writeString(name);
}
public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
// 重写Creator
@Override
public Person createFromParcel(Parcel source) {
Log.d("nimeimei", "11111111111111111111111111createFromParcel");
Person p = new Person();
p.map = source.readHashMap(HashMap.class.getClassLoader());
p.name = source.readString();
Log.d("nimeimei", "11111111111111111111111111createFromParcel"
+ p.map);
return p;
}
@Override
public Person[] newArray(int size) {
// TODO Auto-generated method stub
return null;
}
};
}