Androidの描画処理(Activity.setContentView())

前回はHandlerの話を書いたので関連する話として、Androidの描画処理について書いてみます。
Androidの描画処理の特徴として、描画要求を出してもすぐに描画されるわけではなくAndroid OS側のタイミングにより描画が実行されます。

アプリを開発したことがあれば常識と言っていい話なのですが、どのような仕組みで描画が実行されるかAndroid OS側の処理を見たことがある人は少ないと思います。
今回は描画要求を出した後Android OS側で何が行われているか追ってみます。

確認するソースコードは例によって私がよく使っているAndroid 4.2、追いかける処理はActivityクラスの描画処理としておなじみのsetContentView()から追ってみます。

というわけでActivityクラスのsetContentView()


    public void setContentView(int layoutResID) {
        getWindow().setContentView(layoutResID);
        initActionBar();
    }

ここではWindowクラスのsetContentView()を実行しています。
initActionBar()のほうはActionBarの初期化処理っぽいので割愛します。

WindowクラスのsetContentView()はこんな感じ


    public abstract void setContentView(int layoutResID);

Windowクラスはabstractなので実装したクラスがどこかにいるはずです。

Windowを実装したクラスPhoneWindowのsetContentView()はこんな感じ。


    @Override
    public void setContentView(int layoutResID) {
        if (mContentParent == null) {
            installDecor();
        } else {
            mContentParent.removeAllViews();
        }
        mLayoutInflater.inflate(layoutResID, mContentParent);
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
    }

因みにPhoneWindow.javaはframeworks/base/policy/の下にいます。
ここでやっていることは指定したLayoutのリソースIDをLayoutInflaterでmContentParentに紐づけています。

LayoutInflaterのinflate()の内容はこんな感じ


    public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
~~~~~~~~~~~~~~~中略~~~~~~~~~~~~~~~~~~~~~~~~
                    if (root != null && attachToRoot) {
                        root.addView(temp, params);
                    }

処理が長いので省略しますが、リソースIDを元にXMLをパースし、その情報を基にViewを作成した後上記処理でrootにaddView()しています。

やっと描画処理の入り口addView()にたどり着いたのですが、そこそこ長くなってきたのでaddView()から先は次回読んでいこうと思います。