前回は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()から先は次回読んでいこうと思います。