Revision 4 as of 2010-10-25 14:04:34

Clear message
Locked History Actions

Android/Handler

Handler

Handlerのマニュアルには以下の記述がある。

A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.

が、Javaを知ってる人間がこれを読めば頭の中が「?」で埋め尽くされることは必至である。Javaのスレッドにこんな機能は存在しない。 つくづく不親切な記述である。結局のところ、Androidのソースコードを読まなければこの疑問は解決しない。

ソースを読んでみればすぐに理解できるのだが、Handlerの動作にはLooperというオブジェクトが必要であり、そのLooperオブジェクトはスレッドごとにThreadLocalを使用して保持されているのである。だから、勝手に作成したThreadに対してHandlerを作成しても例外が発生してしまう。このようなスレッドに対してはあらかじめLooperオブジェクトを作成して登録しておかなければならない。

さらに、HandlerにはLooperオブジェクトを引数として与えることのできるコンストラクタが用意されているのだから「of the thread that is creating it」という部分は間違いである。

なぜHandlerは複数作成することができるのか

GUIスレッドとそれ以外のスレッドの同期を行うためなら、Swingにあるような機能(SwingUtilities.invokeLater)で十分であると思われる。 この場合、あらゆる場所からこの同じstaticなメソッドを呼び出すことができる。専用のオブジェクトを作成する必要はない。

Android環境はメモリ量が小さいのだから、どういうわけでSwingよりメモリを要求されるアプローチをとっているのだろうか? 考えられることと言えば、「一つのアプリケーション中の異なるアクティビティのGUIスレッドは異なるものになる」ということしか無いのだが、ほんとうにこのようなことが起こるのだろうか?

確認していないので真偽のほどは確かではないが、もしそうでないとしたら、この機能はあまりに冗長であり、設計ミスと言わざるを得ないだろう。