Parcelable接口是实现序列化的一种方式,与Serializable相比比较复杂,但胜在运行效率高,在安卓中得到了广泛应用。主要需要实现写入和读出两个功能,写入比较易懂,使用 writeToParcel,读出按说也应该是一个方法createFromParcel,但是却将其封装在了Creator类中,这是何故?深入Parcel类的readParcelable方法初步了解读出过程才恍然大悟。
public class User implements Parcelable{
public int userId;
public String userName;
public boolean isMale;
public Book book;
public User(int userId,String userName,boolean isMale){
this.userId = userId;
this.userName = userName;
this.isMale = isMale;
}
public int describeContents(){
return 0;
}
public void writeToParcel(Parcel out,int flag){
out.writeInt(userId);
out.writeString(userName);
out.writeBoolean(isMale);
out.writeParcelable(book,0);
}
//把createFromParcel方法封装进Creator类
public static final Parcelable.CreatorCREATOR = new Parcelable.Creator(){
public User createFromParcel(Parcel in){
return new User(in);
}
public User[] newArray(int size){
return new User[size];
}
}
private User(Parcel in){
userId = in.readInt();
userName = in.readString();
isMale = in.readBoolean();
book = in.readParcelable(Thread.currentThread().getContextClassLoader());
}
}
以下是Parcel类中关于读出的几个方法
public final T readParcelable(ClassLoader loader) {
Parcelable.Creator> creator = readParcelableCreator(loader);//进入
if (creator == null) {
return null;
}
if (creator instanceof Parcelable.ClassLoaderCreator>) {
Parcelable.ClassLoaderCreator> classLoaderCreator =
(Parcelable.ClassLoaderCreator>) creator;
return (T) classLoaderCreator.createFromParcel(this, loader);
}
return (T) creator.createFromParcel(this);
}
public final Parcelable.Creator> readParcelableCreator(ClassLoader loader) {
String name = readString();//获取类名
if (name == null) {
return null;
}
Parcelable.Creator> creator;
synchronized (mCreators) {
//设立一个Map存储Creator,也就是存储读出方法
HashMap> map = mCreators.get(loader);
if (map == null) {
map = new HashMap<>();
mCreators.put(loader, map);
}
creator = map.get(name);
if (creator == null) {
try {
// If loader == null, explicitly emulate Class.forName(String) "caller
// classloader" behavior.
ClassLoader parcelableClassLoader =
(loader == null ? getClass().getClassLoader() : loader);
// Avoid initializing the Parcelable class until we know it implements
// Parcelable and has the necessary CREATOR field. http://b/1171613.
//反射获得Creator类
Class> parcelableClass = Class.forName(name, false /* initialize */,
parcelableClassLoader);
if (!Parcelable.class.isAssignableFrom(parcelableClass)) {
throw new BadParcelableException("Parcelable protocol requires subclassing "
+ "from Parcelable on class " + name);
}
Field f = parcelableClass.getField("CREATOR");
if ((f.getModifiers() & Modifier.STATIC) == 0) {
throw new BadParcelableException("Parcelable protocol requires "
+ "the CREATOR object to be static on class " + name);
}
Class> creatorType = f.getType();
if (!Parcelable.Creator.class.isAssignableFrom(creatorType)) {
// Fail before calling Field.get(), not after, to avoid initializing
// parcelableClass unnecessarily.
throw new BadParcelableException("Parcelable protocol requires a "
+ "Parcelable.Creator object called "
+ "CREATOR on class " + name);
}
creator = (Parcelable.Creator>) f.get(null);//因为是静态的,所以传null即可
}
catch (IllegalAccessException e) {
Log.e(TAG, "Illegal access when unmarshalling: " + name, e);
throw new BadParcelableException(
"IllegalAccessException when unmarshalling: " + name);
}
catch (ClassNotFoundException e) {
Log.e(TAG, "Class not found when unmarshalling: " + name, e);
throw new BadParcelableException(
"ClassNotFoundException when unmarshalling: " + name);
}
catch (NoSuchFieldException e) {
throw new BadParcelableException("Parcelable protocol requires a "
+ "Parcelable.Creator object called "
+ "CREATOR on class " + name);
}
if (creator == null) {
throw new BadParcelableException("Parcelable protocol requires a "
+ "non-null Parcelable.Creator object called "
+ "CREATOR on class " + name);
}
map.put(name, creator);//保存creator
}
}
return creator;
}
Parcel的读写方法继续深入就是C语言了,在C语言层面不存在Java的类和方法,所以传递信息通过字符串或者其他方法,在读取时是从C读到Java,首先通过Class.forName()获得User的Class类ParcelableClass,再通过ParcelableClass.getField("CREATOR")获得Creator属性f,最后通过f.get(null)获得属性f的具体实例CREATOR。为了提高效率避免每次都要获取一遍,就把结果CREATOR存到map中,下一次可以先在map中查找,没有再反射获取。所以Creator的意义在于保存createFromParcel,优化运行效率。