Parcelable接口的使用
转自:Kenny技术博客
什么是Parcelable ?
Parcelable是一个接口、用来实现序列化。与此类似的还有一个接口Serializable
,这是JavaSE本身支持的,而Parcelable
是Android特有的。二者比较:
Parcelable
使用起来稍复杂点,而后者使用起来非常简单。下面例子中会看到。Parcelabl
e效率比Serializable
高,支持Intent数据传递,也支持进程间通信(IPC)。Parcelable
使用时要用到一个Parcel
,可以简单将其看为一个容器,序列化时将数据写入Parcel
,反序列化时从中取出。- 在使用内存的时候,
Parcelable
比Serializable
性能高,所以推荐使用Parcelable。Serializable
在序列化的时候会产生大量的临时变量,从而引起频繁的GC。Parcelable
不能使用在要将数据存储在磁盘上的情况,因为Parcelable
在外界有变化的情况下不能很好的保证数据的持续性。尽管Serializable
效率低点,但此时还是建议使用Serializable
。
Parcelable 传递对象
Android序列化对象主要有两种方法:
1.实现Serializable接口通过intent来传递对象-Serializable方式;
2.实现Parcelable
接口,Parcelable
是Android特有的功能,效率比实现Serializable接口高,像用于Intent数据传递也都支持,而且还可以用在进程间通信(IPC),除了基本类型外,只有实现了Parcelable接口的类才能被放入Parcel中。
源码
package android.os;
/**
* Interface for classes whose instances can be written to
* and restored from a {@link Parcel}. Classes implementing the Parcelable
* interface must also have a non-null static field called <code>CREATOR</code>
* of a type that implements the {@link Parcelable.Creator} interface.
*
* <p>A typical implementation of Parcelable is:</p>
* Parcelable的典型实现是:
* <pre>
* 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();
* }
* }</pre>
*/
public interface Parcelable {
/**
* Flag for use with {@link #writeToParcel}: the object being written
* is a return value, that is the result of a function such as
* "<code>Parcelable someFunction()</code>",
* "<code>void someFunction(out Parcelable)</code>", or
* "<code>void someFunction(inout Parcelable)</code>". Some implementations
* may want to release resources at this point.
*/
public static final int PARCELABLE_WRITE_RETURN_VALUE = 0x0001;
/**
* Bit masks for use with {@link #describeContents}: each bit represents a
* kind of object considered to have potential special significance when
* marshalled.
*/
public static final int CONTENTS_FILE_DESCRIPTOR = 0x0001;
/**
* Describe the kinds of special objects contained in this Parcelable's
* marshalled representation.
* 内容描述接口,基本不用管,return 0;
* @return a bitmask indicating the set of special object types marshalled
* by the Parcelable.
*/
public int describeContents();
/**
* Flatten this object in to a Parcel.
* //写入接口函数,打包
* @param dest The Parcel in which the object should be written.
* @param flags Additional flags about how the object should be written.
* May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
*/
public void writeToParcel(Parcel dest, int flags);
/**
* Interface that must be implemented and provided as a public CREATOR
* field that generates instances of your Parcelable class from a Parcel.
*/
//读取接口,目的是要从Parcel中构造一个实现了Parcelable的类的实例处理。
//因为实现类在这里还是不可知的,所以需要用到模板的方式,继承类名通过模板参数传入。
//为了能够实现模板参数的传入,这里定义Creator嵌入接口,内含两个接口函数分别返回单个和多个继承类实例。
public interface Creator<T> {
/**
* Create a new instance of the Parcelable class, instantiating it
* from the given Parcel whose data had previously been written by
* {@link Parcelable#writeToParcel Parcelable.writeToParcel()}.
*
* @param source The Parcel to read the object's data from.
* @return Returns a new instance of the Parcelable class.
*/
public T createFromParcel(Parcel source);
/**
* Create a new array of the Parcelable class.
*
* @param size Size of the array.
* @return Returns an array of the Parcelable class, with every entry
* initialized to null.
*/
public T[] newArray(int size);
}
/**
* Specialization of {@link Creator} that allows you to receive the
* ClassLoader the object is being created in.
*/
public interface ClassLoaderCreator<T> extends Creator<T> {
/**
* Create a new instance of the Parcelable class, instantiating it
* from the given Parcel whose data had previously been written by
* {@link Parcelable#writeToParcel Parcelable.writeToParcel()} and
* using the given ClassLoader.
*
* @param source The Parcel to read the object's data from.
* @param loader The ClassLoader that this object is being created in.
* @return Returns a new instance of the Parcelable class.
*/
public T createFromParcel(Parcel source, ClassLoader loader);
}
}
怎么实现Parcelable接口?
从parcelable接口定义中,我们可以看到,实现parcelable接口,需要我们实现下面几个方法:
describeContents
方法。内容接口描述,默认返回0就可以;writeToParcel
方法。该方法将类的数据写入外部提供的Parcel
中.即打包需要传递的数据到Parcel
容器保存,以便从parcel
容器获取数据,该方法声明如下:writeToParcel (Parcel dest, int flags)
静态的
Parcelable.Creator
接口,本接口有两个方法:createFromParcel(Parcel in)
从Parcel
容器中读取传递数据值,封装成Parcelable
对象返回逻辑层。newArray(int size)
创建一个类型为T,长度为size的数组,仅一句话(return new T[size])
即可。方法是供外部类反序列化本类数组使用。
代码实现
1.封装数据,把实现parcelable接口的Person对象传递到TwoActivity里;
public class DemoActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 封装数据
Person p = new Person();
p.setId(1);
p.setName("xiaoming");
// 用Intent传递Person对象
Intent i = new Intent(this, TwoActivity.class);
i.putExtra("Person", p);
startActivity(i);
}
}
2.TwoActivity获取数据,从DemoActivity传递的Person对象给解析
public class TwoActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Person p = (Person)getIntent().getParcelableExtra("Person");
System.out.println("p_id"+p.getId());
System.out.println("p_name"+p.getName());
}
}
3.parcelable接口的实现
public class Person implements Parcelable{
// 成员变量
private int id;
private String name;
// 1.必须实现Parcelable.Creator接口,否则在获取Person数据的时候,会报错,如下:
// android.os.BadParcelableException:
// Parcelable protocol requires a Parcelable.Creator object
// called CREATOR on class com.um.demo.Person
// 2.这个接口实现了从Percel容器读取Person数据,并返回Person对象给逻辑层使用
// 3.实现Parcelable.Creator接口对象名必须为CREATOR,不如同样会报错上面所提到的错;
// 4.在读取Parcel容器里的数据事,必须按成员变量声明的顺序读取数据,不然会出现获取数据出错
// 5.反序列化对象
public static final Parcelable.Creator<Person> CREATOR = new Creator(){
@Override
public Person createFromParcel(Parcel source) {
// TODO Auto-generated method stub
// 必须按成员变量声明的顺序读取数据,不然会出现获取数据出错
Person p = new Person();
p.setId(source.readInt());
p.setName(source.readString());
return p;
}
@Override
public Person[] newArray(int size) {
// TODO Auto-generated method stub
return new Person[size];
}
};
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
// 1.必须按成员变量声明的顺序封装数据,不然会出现获取数据出错
// 2.序列化对象
dest.writeInt(id);
dest.writeString(name);
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 bin07280@qq.com
文章标题:Parcelable接口的使用
文章字数:1.7k
本文作者:Bin
发布时间:2016-05-14, 09:49:24
最后更新:2019-08-06, 00:07:35
原始链接:http://coolview.github.io/2016/05/14/Android/Parcelable%E6%8E%A5%E5%8F%A3%E7%9A%84%E4%BD%BF%E7%94%A8/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。