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
Rubyのモジュール機能とRailsのHelperについて考える

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

no image
SwiftでOSのバージョンが8.0.0以下とそれより大きいヤツで処理を分岐させたい

前置き push通知のデバイストークン取得方法がiOS8から変わりました。 …

no image
アプリ起動時に呼び出すStoryboardを指定したい

google-fu不足でどこにも載ってなかったのでメモ。 プロジェクト内のInfo.plistで設定できます。 …

no image
gitであまり使わないけど知らないと困るコマンド一覧

随時追加 originのURLを変更したい …

no image
DockerでNginxしたい

Contents1 Dockerfileを用意する2 …

no image
意識低いRuby on Rails再入門1

整理がてらメモ。 Contents1 …

no image
ファイルとかのパーミッションを再帰的に変更したい

あるディレクトリ以下全ファイルのパーミッションを再帰的に変更 chmod …

MacでDockerした感想文

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

no image
Mastodonインスタンス(お一人様用)を作り方メモ

Mastodonは運営の存在を気にせず罵詈雑言吐けるの便利そう。 自分用のインスタンス作ったので、便所の落書きしておく。 …

no image
RubyMine(OSX)でGit操作するときのコマンド集

GITを操作系のポップアップを表示したい