Android Parcel和Parcelable类

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chennai1101/article/details/87267735

1. Parcel类

Parcel主要用于在进程间通讯,传递数据。
Parcel通过obtain()静态方法获取,数据的存储和读取主要通过writeXXX()readXXX()实现,marshall()unmarshall()将数据序列化和反序列化,最后recycle()回收资源。

public byte[] writeValue() {
    Parcel data = Parcel.obtain();
    try {
        data.writeInt(12);
        data.writeDouble(34.5);
        data.writeString("This is a string");
        return data.marshall();
    } finally {
        data.recycle();
    }
}
public void readValue(byte[] bytes) {
    Parcel reply = Parcel.obtain();
    try {
        reply.unmarshall(bytes, 0, bytes.length);
        reply.setDataPosition(0);

        reply.readInt();
        reply.readDouble();
        reply.readString();
    } finally {
        reply.recycle();
    }
}

2. Parcelable类

Parcelable是个接口,用于数据的传递。
Parcel中,存储Parcelable数据,调用Parcelable.writeToParcel(Parcelable, int)方法。

public final void writeParcelable(Parcelable p, int parcelableFlags) {
    if (p == null) {
        writeString(null);
        return;
    }
    writeParcelableCreator(p);
    // Parcelable.writeToParcel方法
    p.writeToParcel(this, parcelableFlags);
}

而读取Parcelable数据时,调用Creator的子类,并调用createFromParcel()方法来读取

public final <T extends Parcelable> T readParcelable(ClassLoader loader) {
    // 获得Parcelable中的CREATOR类
    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) {
        HashMap<String,Parcelable.Creator<?>> map = mCreators.get(loader);
        if (map == null) {
            map = new HashMap<>();
            mCreators.put(loader, map);
        }
        // 如果有缓存,直接读取create
        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.
                Class<?> parcelableClass = Class.forName(name, false /* initialize */,
                        parcelableClassLoader);
                if (!Parcelable.class.isAssignableFrom(parcelableClass)) {
                    throw new BadParcelableException("Parcelable protocol requires that the "
                            + "class implements Parcelable");
                }
                // 查看是否存在名字为CREATOR的静态属性
                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);
            }
            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);
        }
    }

    return creator;
}

实现Parcelable步骤

  • 必须要 implement Parcelable
  • 重写describeContents()方法
  • 重写writeToParcel(Parcel, int)方法
  • 实例化静态内部对象CREATOR实现接口Parcelable.Creator

ParcelableValue类继承Parcelable,

public class ParcelableValue implements Parcelable {

    private int i;
    private double d;
    private String s;

    public ParcelableValue(int i, double d, String s) {
        this.i = i;
        this.d = d;
        this.s = s;
    }

    public ParcelableValue(Parcel data) {
        i = data.readInt();
        d = data.readDouble();
        s = data.readString();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(i);
        dest.writeDouble(d);
        dest.writeString(s);
    }

    public static final Creator<ParcelableValue> CREATOR = new Parcelable.Creator<ParcelableValue>() {

        @Override
        public ParcelableValue createFromParcel(Parcel source) {
            return new ParcelableValue(source);
        }

        @Override
        public ParcelableValue[] newArray(int size) {
            return new ParcelableValue[size];
        }
    };

}

3. 与Serializable序列化比较

  • 在使用内存的时候,ParcelableSerializable性能高。
  • Parcelable不能使用在要将数据存储在磁盘上的情况

猜你喜欢

转载自blog.csdn.net/chennai1101/article/details/87267735