moxt

Just another Blog site

AndroidのHandlerって何?

      2015/07/03

Handlerは何?と、Handlerを直視するとHandlerの存在意義というかなんというか文脈を捉えることが難しい。
なので、まずはAndroidがシングルスレッドである、という所からスタートしてHandlerに向かってゆく。

Androidはシングルスレッド

AndroidはJavascriptやActionscriptのように1つのループがグルグル回ってイベントを逐次捌くシングルスレッド方式。
なので、各イベント内で重い処理やブロッキングが発生するような処理(同期的なHTTP通信とか?)走らせると処理落ちが発生してアプリの動作がカクつく。

Androidでマルチスレッドしたい

なので、先にあげたHTTP通信とか大量の計算が必要な処理をしたいときはメインのスレッドとは別のスレッドを生成、そのスレッド内で処理を行うようにする。

こんな感じ

Threadを継承して独自の処理を記述する
Runnableを実装したインスタンスをThreadインスタンス生成時に与える

スレッド内で処理が完結するならこれで終わり。

スレッド間で通信したい

完結しない場合もある。
例えば、HTTP通信してきた結果をTextViewに表示したい。とか。
スレッドにViewの参照渡して更新したらいいんじゃないの?って思うんだけど、それができないようになってる。
UI系の更新処理はメインスレッド上で呼び出さないとダメなんだって。
こういう別スレッド云々関係なく、普段のUI系の更新処理もメインスレッド上で行ってる。
処理をあちこちのスレッドから実行せず集約することでカオスにならないようにしてるのかな。

というわけで、メインスレッドに対して何かしらの方法で処理の内容を伝えないといけない。
どうやるのか?

ある別スレッド→メインスレッド

想像するに2つのステップがある気がする

  • 別スレッドはメインスレッドに対して何かしらの方法で処理の内容を投げる
  • メインスレッドは別スレッドからとんできた処理内容のメッセージを受け取って、そこに書いてる処理を実行する

真打ちHandler

ここでHandlerとLooperが登場するわけ。

http://tachesimazzoca.github.io/wiki/android/threads.html

Android では、スレッド毎に MessageQueue を持ち、Looper が順番に送信されたメッセージをキューから取り出し、処理を行なっている。

Handler により、このキューにメッセージを送信することができる。

どのメッセージキューに対してメッセージを送信するか、と指定するわけではない。ちょっと混乱する。
MessageQueueからメッセージを取り出すLooperを指定してメッセージを送るようなかんじ。

http://d.hatena.ne.jp/sankumee/20120329/1333021847

↑この記事が分かりやすかった。
Handlerインスタンスを生成するときに送り先Looperを指定してる。
で、post(Message) or post(Runnable)って感じ。

Looper.getMainLooper()っていうメソッドがあって、これを呼べばメインスレッドに紐づくLooperが取得できる。
なので、Looper.getMainLooperの返り値をHandlerに注入してインスタンス作ってやればOK

ちなみ、メインスレッドのLooperはAndroidアプリ起動時に勝手につくられるみたい。
なので、明示的にprepareする必要はない。
詳細はgrepcodeで確認できる。

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/1.5_r4/android/os/Looper.java#Looper.myLooper%28%29

おわり

Handler系の記事はもっと洗練されたヤツあるので、いまさら感ある。
でも、こういう感じで書きながら流れに沿って理解をするってのは血肉度高まるし良いよね。

 - プログラミング

  • このエントリーをはてなブックマークに追加
  • follow us in feedly

  関連記事

no image
iOSアプリの設計ってどうやるの?

ViewControllerに処理を詰め込みすぎて保守が大変になるのはあるあるネタですよね。 じゃあ、ViewControllerでやることってなんだろうって問われると、まあ、こんなんだろうなってフワッとしてる。 …

no image
sudo gem install cocoapods –preしても0.36.0が使えないとき

最新のcocoapodsそのものはインストールされてる。 なので、podコマンドを実行するときに下記のようにバージョンを指定すれば一応使える。 …

ReactなComponent同士を連携させたい

実践的なサンプルに塗れてなんとなく使ってると破綻する。 分かってること、分かってないことを整理しておきたい。 …

no image
MecabをPythonから使いたい

ベイズ分類器を自分で作りたかった。 そのためには、文書を単語の集合に変換する必要がある。 …

no image
NginxとPHP-FPMを使っていたらcurl_init()が無いとエラーが出た

参考リンク 解決策 …

no image
Docker導入したらどうするの?

Dockerを導入したけど、nginxが入った環境がどこでも使えるようになった!程度だったらあんま意味ないよね。 Web開発をする上でDockerをどのように使うのが効果的か考えてみる。 …

no image
GrowthPushのAndroid-SDK(?)のコードを読んでみる

できること、できないことを知るために。 GrowthPush.java …

no image
単語の出現頻度をlinuxコマンドだけで調べたい

無駄にpythonとか使おうとしてた。。 楽にできて良かった。 …

no image
Rubyのモジュール機能とRailsのHelperについて考える

Moduleとは 参考サイトを見ながら思ったことをメモ …

MacでDockerした感想文

Contents1 前提:DockerはLinux上でしか動かない1.1 …