1.Parcelable,定义了将数据写入Parcel,和从Parcel中读出的接口。一个实体(用类来表示),如果需要封装到消息中去,就必须实现这一接口,实现了这一接口,该实体就成为“可打包的”了。
接口的源码如下:
public interface Parcelable {
//内容描述接口,基本不用管
public int describeContents();
//写入接口函数,打包
public void writeToParcel(Parcel dest, int flags);
//读取接口,目的是要从Parcel中构造一个实现了Parcelable的类的实例处理。因为实现类在这里还是不可知的,所以需要用到模板的方式,继承类名通过模板参数传入。
//为了能够实现模板参数的传入,这里定义Creator嵌入接口,内含两个接口函数分别返回单个和多个继承类实例。
public interface Creator<T> {
public T createFromParcel(Parcel source);
public T[] newArray(int size);
}
}
2.类的写法:
package com.ysl.myandroidbase.bean;
import android.os.Parcel;
import android.os.Parcelable;
public class Cat implements Parcelable {
public String name;
public int age;
public Cat() {
}
public Cat(Parcel source) {
this.name = source.readString();
this.age = source.readInt();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
dest.writeInt(this.age);
}
public static final Creator<Cat> CREATOR = new Creator<Cat>() {
@Override
public Cat createFromParcel(Parcel source) {
return new Cat(source);
}
@Override
public Cat[] newArray(int size) {
return new Cat[size];
}
};
}
主要是要重写describeContents()、writeToParcel(Parcel dest, int flags)方法。
CREATOR:
/**
* public static final一个都不能少,内部对象CREATOR的名称也不能改变,必须全部大写。
* 重写接口中的两个方法:
* createFromParcel(Parcel in) 实现从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层,
* newArray(int size) 创建一个类型为T,长度为size的数组,供外部类反序列化本类数组使用。
*/
public static final Creator<Cat> CREATOR = new Creator<Cat>() {
/**
* 从序列化后的对象中创建原始对象
*/
@Override
public Cat createFromParcel(Parcel source) {
return new Cat(source);
}
/**
* 创建指定长度的原始对象数组
*/
@Override
public Cat[] newArray(int size) {
return new Cat[size];
}
};
3.Intent数据传输:
发送数据:
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
Bundle bundle = new Bundle();
Cat cat = new Cat();
cat.name = "tom";
cat.age = 1;
bundle.putParcelable("cat", cat);
intent.putExtras(bundle);
startActivity(intent);
接收数据:
Cat cat = getIntent().getParcelableExtra("cat");
TextView tv3 = findViewById(R.id.tv3);
tv3.setText(cat.name+"_"+cat.age);
4.Parcelable需要实现writeToParcel、describeContents函数以及静态的CREATOR变量,实际上就是将如何打包和解包的工作自己来定义。
Parcelable的性能,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如activity间传输数据,进程间的数据传输。但写法稍微复杂,并且因为android不同版本Parcelable可能不同,所以不推荐使用Parcelable进行数据持久化,只推荐内存数据的传输。
5.AndroidStudio使用parcelable插件
安装好插件以后,写好类以及要使用的字段:
package com.ysl.myaidl.bean;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
public class ParcelableBean implements Parcelable {
String aString;
int aInt;
double aDouble;
HashMap<String, String> aHashMap;
ArrayList<String> aArrayList;
DemoAnotherClass anotherClass;
class DemoAnotherClass{
ConcurrentHashMap<String, String> aConcurrentHashMap;
}
}
选中类名,按alt+insert键,选择最下面的parcelable,立马生成代码。
package com.ysl.myaidl.bean;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
public class ParcelableBean implements Parcelable {
String aString;
int aInt;
double aDouble;
HashMap<String, String> aHashMap;
ArrayList<String> aArrayList;
DemoAnotherClass anotherClass;
static class DemoAnotherClass implements Parcelable{
ConcurrentHashMap<String, String> aConcurrentHashMap;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeSerializable(this.aConcurrentHashMap);
}
public DemoAnotherClass() {
}
protected DemoAnotherClass(Parcel in) {
this.aConcurrentHashMap = (ConcurrentHashMap<String, String>) in.readSerializable();
}
public static final Creator<DemoAnotherClass> CREATOR = new Creator<DemoAnotherClass>() {
@Override
public DemoAnotherClass createFromParcel(Parcel source) {
return new DemoAnotherClass(source);
}
@Override
public DemoAnotherClass[] newArray(int size) {
return new DemoAnotherClass[size];
}
};
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.aString);
dest.writeInt(this.aInt);
dest.writeDouble(this.aDouble);
dest.writeSerializable(this.aHashMap);
dest.writeStringList(this.aArrayList);
dest.writeParcelable(this.anotherClass, flags);
}
public ParcelableBean() {
}
protected ParcelableBean(Parcel in) {
this.aString = in.readString();
this.aInt = in.readInt();
this.aDouble = in.readDouble();
this.aHashMap = (HashMap<String, String>) in.readSerializable();
this.aArrayList = in.createStringArrayList();
this.anotherClass = in.readParcelable(DemoAnotherClass.class.getClassLoader());
}
public static final Creator<ParcelableBean> CREATOR = new Creator<ParcelableBean>() {
@Override
public ParcelableBean createFromParcel(Parcel source) {
return new ParcelableBean(source);
}
@Override
public ParcelableBean[] newArray(int size) {
return new ParcelableBean[size];
}
};
}
内部类要改成static的,而且也要实现parcelable接口,否则会报错。