AIDLを使って非同期のプロセス間通信を行う

お久しぶりです。大分更新の間が開いてしまいました。
仕事が忙しかった、私生活がバタバタしていたというわけではなく、
部屋掃除していたら出てきたゲームをプレイしたところハマってしまったことが原因です。
概ね遊びつくしたのでもうそのゲームをやる気はないのですが、
ゲームをやっていた期間は本当にゲーム漬けの生活を送っていました。
仕事から帰宅してはゲーム!土日も当然一日中ゲーム!という見るも無残な生活だったわけです。
のめりこんで破滅するタイプなので今後ゲームに手を出すときは気を付けようと思います。

今回はタイトル通りAndroidのAIDLを使った非同期のプロセス間通信について書こうと思います。
プロセス間通信なので当然サービスを作ったりするわけですが、サービスの作り方については割愛します。

サンプルアプリのソースコードはこちらです。

〇サンプルアプリの概要
・同期実行ボタンを押すとサービスから同期処理で文字列を取ってきてその文字を表示する
・非同期実行ボタンを押すとサービスから非同期で文字列を取得してその文字を表示する

以上、何の面白みもないアプリです。

〇同期実行
このサンプルアプリでサービスから同期で文字列を処理しているメソッドは以下のものになります。
ISampleService.Stub#syncGetStringFromService
これはサービスのメインスレッド的なところで処理が行われてるみたいなんですが、
結局UIスレッドはその処理が終わるまでブロックされてるっぽいので結果として同期されています。AIDLを普通に実装すれば必然的に同期処理になります。

〇非同期実行
しかしわざわざ別プロセスを立てているのだから非同期で処理を行いたいというもの。
非同期でプロセス側からコールバックを返すためには以下のことが必要になります。
・Activityからの要求を受けてそれ処理をするサービス側のスレッド
・コールバック用のAIDLファイル
・RemoteCallbackList

・Activityからの要求を受けてそれ処理をするサービス側のスレッド
サンプルアプリではBackgroundQueueというクラスがそれになります。
しっかりテストしてないのでどこかしら粗はあると思いますが。
スレッドを立ててBackgroundQueue#enqueueでRunnableがキューに入ったら
そのスレッドで実行するワークキューみたいなものです。

・コールバック用のAIDLファイル
ISampleServiceCallback.aidlがこれになります。
サービスからActivityにデータを送りつけるためのIFです。
これをISampleService#registerCallbackでサービス側に渡してコールバックする流れです。

・RemoteCallbackList
詳細は公式ドキュメントに譲ります。
サービスからコールバックでプロセス間通信を行う場合はこれを使ってねってやつです。
RemoteCallbackList#registerでコールバックを登録したら以下の流れでコールバック関数を呼びます。

1.実際にコールバックするタイミングでRemoteCallbackList#beginBroadcast呼ぶ
2.コールバック関数を呼ぶ
3.RemoteCallbackList#finishBroadcastを呼ぶ

サンプルアプリだとISampleService.Stub#asyncGetStringFromServiceがその辺の実装になります。

サンプルアプリの非同期シーケンスはこんな感じです。

うーん、普通に分かりにくいし実行しているスレッドが本当にあってるかも自信はないです。
デバッグ実行してる感じだとコールバックを実行してるスレッドとワーカスレッドは別ぽいです。
プロセス間通信周りはどんなスレッドがいてどこのスレッドで何やってるのかがまとまってるドキュメントとかないものかって感じです。

〇Splash画面からサービスの初期化完了を受けて画面遷移する
スプラッシュ画面なるものがあるそうです。
なぜスプラッシュ画面なるものがいるのか、詳しい話は全然聞いた事がないのでただの予想ですが、やっぱり初期化とかをスプラッシュ画面でやってるのかな?

そんなわけでサービスで時間のかかる初期化が必要で、サービスの初期化完了をActivityが受けたら別の画面に遷移する、みたいな感じの処理をfeature/splashに入れておきました。(そんなケースは一般的なのか、そうでないかは判断しようがないのだけれども・・・)


シーケンスはこんな感じです。あと画面遷移後のサービスの扱いとかは超適当です。多分間違ってる気がします。
全体的に排他やらなんやらがガバガバ気味なので使う場合は自己責任でお願いします!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

:)