为什么安卓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.Creator CREATOR = 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,优化运行效率。

你可能感兴趣的:(安卓学习笔记,Parcelable,android,序列化,Binder)