SyntaxHighlighter

2013年6月9日日曜日

イベントバスライブラリOtto

Androidのアプリ内でIntentServiceとか使った時に、処理の完了をIntentやCallbackでActivityに通知するコードを毎回書いていて不毛だなーと思っていたら、Ottoという便利そうなライブラリを見つけた。
※確かIntelliJにRobolectricのPluginが無いか探してるときに発見したような気がする。世の中何がきっかけになるかわかりませんな。
で、備忘も兼ねて導入と利用のポイントとして次のことをメモっておく。
  1. Ottoとは
  2. 導入
  3. 前準備
  4. イベント送信/受信
  5. Produce
  6. AndroidAnnotationsとの相性
1. Ottoとは
Ottoは最近日本にも進出したSquareがオープンソースで開発しているイベントバスのライブラリで、出来ることは単純だけど、その分シンプルで気軽に使える。
(個人的にはライブラリってのはこうあるべきだと思う)
とりあえずは、アプリ内IntentとかCallback的なイベントハンドリングのコードが超簡単に書けると思っておけばオッケー。

2. 導入
導入は本当に何も難しくなくて、「公式サイト見てくれ」状態。

2-1-a. pomる
最近はAndroidでもmavenってる人も多いと思うけど、その場合はpomのdependenciesに以下を追加するだけ。Gradleでも基本変わらないハズ。多分。
もちろん、バージョンはこれを書いている時の話だから、導入時に公式サイトでチェックした方が良いと思う。

2-1-b. libsる
公式サイトでjarを落とすこともできるので、それを普通にlibsに突っ込んでもOK。

2-2. proguard対策
Ottoはアノテーションを使って呼び出すメソッドを特定する。その都合で、呼び出すメソッドがproguard的に使われてないからいらないと判断されて捨てられてしまう可能性がある。その対策として、proguard-project.txtに以下を追記しておく。
3. 前準備
Ottoでイベントの送受信をする際に、重要となるのがBusクラスのインスタンス。Busクラスのインスタンスはイベントを送受信するそれぞれのクラスで必要なので、Singletonな管理クラスを1つ作ってそこで管理してしまうのが良いだろう。
と、いうことで次のようなクラスを作っておく。
ここで、new Bus()するときにThreadEnforcerなる引数を渡すことができる。これにより、Busにイベントを登録する(=イベントを実行する)スレッドの種類を限定することができる。限定した種類意以外のスレッドからイベントが登録された場合、例外が発生する。 デフォルトではThreadEnforcer.MAINが指定されていて、メインスレッド(=UIスレッド)からしかイベントが登録できなくなっている。どのスレッドが登録しても良い場合はThreadEnforcer.ANYを引数に指定すれば良い。

4. イベント送信/受信
ここまでくればイベント送信と受信は簡単。

4-1. イベント送信
より簡単なイベント送信から。イベント送信はBusクラスのインスタンスを取得して、イベントとして送信したいクラスのインスタンスをpostすればOK。
ここで送信したクラスの種類によって、受信するメソッドを分けられるのだが、この辺は自然につくっていれば上手くいくはず。
4-2. イベント受信
イベントを受信するには、@Subscribeアノテーションをつけたメソッドを持ったクラスを作り、そのクラスのインスタンスをBusのregister/unregisterを使って登録する必要がある。
register/unregisterはライフサイクル(※)に合わせて実行する必要がある。
※もちろん、クラスのライフサイクルに厳密に合わせる必要はなく、受信が必要になったらregisterして、不要になったらunregisterすれば良い。
Activityであれば、onResumeでregisterして、onPauseでunregisterするような形になるだろう。
5. Produce
Ottoの最後のメイン機能であるProduceは、@Subscribeなメソッドがregisterされた瞬間にイベントを発行するという、ちょっとわかりにくい機能である。
使いどころは、常にある値が時々変動しているような場合に、その値をイベントで追跡したい場合に、初期値を取得するような時だと思われる。
具体例としては、例えば温度センサのイベントを作った場合、Produceを使えば、「温度センサを使うと言った時点の温度(Produceでイベント通知)」と「温度が変化した際の温度(Bus#postでイベント通知)」の両方のイベントを送信できる。
使い方は、@Subscribeと同様、register/unregisterするようにした上で、イベントとして渡すクラスのインスタンスを生成するメソッドを作り、@Produceアノテーションを作るだけである。
6. AndroidAnnotationsとの相性
最後にAndroidAnnotationsと併用する際の注意点を。
AndroidAnnotationsと併用する場合、AndroidAnnotationsのバージョン3.0以上を使うこと。(2013/6/9時点で3.0SNAPSHOTしかないが…)
これは、Ottoが性能を出すために、@Subscribe/@Produceの探索をする際に継承関係まで辿らないことと、AndroidAnnotationsがActivityを継承したActivity_を作って使用することが組み合わさって、イベントが正常にメソッドを起動できなくなるからである。
AndroidAnnotationsの3.0-SNAPSHOTからは、@Subscribe/@Produceのメソッドを継承先でも用意するようになっているので、問題は発生しなくなっている。