AndroidのMessage.sendToTarget()の動作を調べた

com.android.internal.app.AlertControllerを読んでます。

とりあえずsendToTargetはHandlerに対して、sendMessage(this)をしているだけです。

ここのHandlerはMessage.obtain(handler, what, listener)で指定したhandlerです。
thisはもちろんMessage。

ではHandler.sendMessage(Message msg)は何をしているのかという話です。

Handler.sendMessage(Message msg)はHandler.sendMessageDelayed(Message msg, 0)を呼んでいるだけで、sendMessageDelayedではsendMessageAtTimeを呼んでいるだけです。
sendMessageAtTimeを呼び出すときにシステムクロックの現在時刻を引数に渡しています。

Handler.sendMessageAtTimeは、MessageQueueにMessageオブジェクトと時刻を渡してキューイングしています。

あとはAndroidの肝であるLooperがメッセージを実行します。
msg.target.dispatchMessage(msg);

msg.targetは先ほどのHandlerです。

Handler.dispatchMessage(msg)は、msg.callbackが定義されていればmsg.callback.run()を実行しますが、前述のobtainでMessageオブジェクトを作った場合はcallbackは定義されていないので、代わりにHandlerのインスタンスを作ったときに渡されたコールバックがあれば、そちらを実行します。

大抵の場合、コールバックをコンストラクタに渡さずに、Handlerを継承するかしてhandleMessageをオーバーライドするかと思います。
オーバーライドしないと、Handler.handleMessageは何もしません。
    public void handleMessage(Message msg) {
    }

ということで、結局、Looperのキューを介して自前のHandlerに処理が戻ってくるという流れでした。
処理をHandlerにまとめて書くのでなければ、handleMessageを書かずにMessageにコールバックを渡しておくというのでもいいですね。
ただし、Message.obtain(Handler h, Runnable callback)で渡しておく必要があります。
その場合、Runnableが渡せるのはHandler.obtainMessageにはないので、Message.obtainでMessageを作ることになります。

何というか、一目瞭然な図が欲しい。


タグ:

新しく会社作りました!

コメントをどうぞ