July 4, 2012

アプリケーションとLooperとHandlerの関係

アプリケーションとLooperとHandlerの関係についての説明です。Androidフレームワークの内部に踏み込んだお話です。

「スレッドからUIを操作する」で、UIスレッドで実行させるために他のスレッドからHandlerクラスを使って処理内容を送信すると説明しましたが、なぜnew Handler()としただけのインスタンスにpost()しただけでUIスレッドに送信されてしまうか?という疑問への回答です。

まずAndroidのアプリケーションは1つのプロセスが割り当てられて動作しています。別々のアプリは別々のプロセス(つまりメモリ空間が異なる)で動いています。

UIスレッドとはメインスレッドとも呼ばれ、内部ではActivityThreadクラスのことを指します。このクラスはStatic変数のLooperクラスを所持しており(つまり1プロセスに1つしかない)、メイン関数でLooperクラスのメインループを実行しています。Looperクラスの処理は単純で、メッセージキューに入ってきた処理があれば実行する、だけです。つまりどこかのスレッドからメッセージをLooperに送信すれば、ActivityThread(UIスレッド)で実行してくれるという仕組みになっています。その送信するのがHandlerクラスになります。Handlerクラスは引数なしでnewすると内部でStatic変数のLooperクラスを送信先とします。つまりActivityThreadが送信先になるということです。

ここでいうメッセージとは、内部ではMessageクラスを使っており、Handlerのインスタンスでpost()するときのRunnableインスタンスを渡しています。それがLooperのメイン関数で、渡されたRunnableのrun()を実行しています。

より詳細はAndroidのソースコードを読む必要があります。
  • android/os/Handler.java
  • android/os/Looper.java
  • android/os/Message.java
  • android/app/ActivityThread.java
ちなみに、このLooper、Handlerの仕組みは独自に他のスレッド同士で利用することも可能です。引数を指定することでUIスレッドとは無関係に、独自で作ったスレッド間で同じ仕組みを利用できます。

No comments:

Post a Comment