android access 内部类,为什么安卓Parcelable接口会有一个内部类Creator

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,优化运行效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值