小包の包み方

createFromParcelメソッドからして、非直列化はこのインタフェースを介して行うらしいが、どうしてこんな作りになっているんだろう。

前にも書いたが、Androidではアプリケーション(ActivityやService)間が分離されており、オブジェクトやデータを共有することできないので、何らかのメッセージ通信のメカニズムが必要になる。

AndroidはIntent(インテント)という簡易なプロセス間通信(Windowsで言うところのDDEに近い)のメカニズムを実装しており、ParcelクラスはParcelableを含む、Androidアプリケーション間で通信するオブジェクトをインテントを介して直列/非直列化する。

実際のParcelクラス中、Parcelableを読込むためのreadParcelableメソッドを見てみよう。

  • Parcel#readParcelable
public final  T readParcelable(ClassLoader loader) {
    String name = readString();
    if (name == null) {
        return null;
    }
    Parcelable.Creator creator;
    synchronized (mCreators) {
        HashMap map = mCreators.get(loader);
        if (map == null) {
            map = new HashMap();
            mCreators.put(loader, map);
        }
        creator = map.get(name);
        if (creator == null) {
            try {
                Class c = loader == null ?
                    Class.forName(name) : Class.forName(name, true, loader);
                Field f = c.getField("CREATOR");
                creator = (Parcelable.Creator)f.get(null);
            }
            catch (IllegalAccessException e) {
                Log.e("Parcel", "Class not found when unmarshalling: "
                                    + name + ", e: " + e);
    :
    :
        return creator.createFromParcel(this);
:

Parcelableの実装クラスに"CREATOR"という名でParcelable.Creatorの実装をしておけば、読み込み時に、意図した非直列化時のためのロジックを呼んで貰うことができる訳だ。

前回のエントリで話題にしたKeyEventクラスを見てみよう。

public static final Parcelable.Creator CREATOR
        = new Parcelable.Creator() {
    public KeyEvent createFromParcel(Parcel in) {
        return new KeyEvent(in);
    }

    public KeyEvent[] newArray(int size) {
        return new KeyEvent[size];
    }
};
〜
private KeyEvent(Parcel in) {
    mAction = in.readInt();
    mKeyCode = in.readInt();
    mRepeatCount = in.readInt();
    mMetaState = in.readInt();
    mDeviceId = in.readInt();
    mScancode = in.readInt();
    mFlags = in.readInt();
    mDownTime = in.readLong();
    mEventTime = in.readLong();
}

JavaにはSerializableという汎用の直列化の仕組みがあるが、基本的に使う側の責任において実装するものであり、外部から全面的にはその実装を信用できない。また、配列やリストを普通に直列化/非直列化することは非常に効率が悪いので、Androidはそれを嫌い、Parcelableという仕組みを用意したのだろう、と勝手に妄想。

やっぱりソースコードを読めるってことはいいなぁ。ドキュメントが完全に邦訳されないうちはソースコードが一番のドキュメントだ。