EventBusって便利ですよね。
特に便利さを実感できるのがActivityとServiceで通信したいときだとおもいます。
ほんとうだったら、BroadcastReceiverクラスを作成して、Actionを定義して、、、としないといけないのですが、EventBusだったらregister
して@Subscribe
するだけで済みます。
しかし、EventBusで賄えないこともあります。
android:process
を使ってServiceが別プロセスで動いているときです。
EventBusは同じプロセス内のクラスにしか届きません。
HermesEventBus
HermesEventBusというライブラリを使えば、プロセス間で通信することができます。
使い方は、以下のような感じ。
HermesEventBus.getDefault().register(this);
HermesEventBus.getDefault().post(new HogeEvent());
このように頭にHermesを付けるだけで、EventBusとほぼ同じように使うことができます。
実際に、別プロセスで動いているServiceに通知できるサンプルコードを作ってみました。
サンプル
通知するイベントは以下のような感じ。
public class GreetEvent {
private String message;
public GreetEvent(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
だめな例
まずはふつうにEventBusを使ってみた場合。
最初はServiceです。
EventBusに登録して、@Subscribe
を使ったメソッドを定義しておきます。
public class MyService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
EventBus.getDefault().register(this);
return super.onStartCommand(intent, flags, startId);
}
@Subscribe
public void onGreet(GreetEvent event) {
Toast.makeText(this, event.getMessage(), Toast.LENGTH_LONG).show();
}
}
別プロセスで動かすのでマニフェストは以下のようになっています。
<service
android:name=".MyService"
android:process=".myservice"
... />
android:process
を指定しています。
そして、Activityでpostしてみます。
もちろんpostするのはServiceを起動したあとです。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
EventBus.getDefault().post(new GreetEvent("Hello"));
}
}
結果
とうぜん、このコードではServiceはイベントを受け取ることはできません。
EventBusはプロセス間通信には対応していないからです。
では、このコードをHermesEventBusを使うように変更してみましょう。
よい例
初期設定
はじめに、build.gradle
に追加しておきましょう。
dependencies {
...
compile 'xiaofei.library:hermes-eventbus:0.3.0'
}
HermesEventBusを使うにはまず、Applicationクラスで初期化する必要があります。
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
HermesEventBus.getDefault().init(this);
}
}
ここで少々手続きが必要です。
というのも、HermesEventBusは古いサポートライブラリに依存しているようで、このままだとActionBarActivity
が見つからないと言うエラーが発生してしまいます。
対処法は以下の参照先のように、android.support.v7.app
パッケージの中に、ActionBarActivity
を自分で作っておきます。
package android.support.v7.app;
public class ActionBarActivity extends AppCompatActivity { }
适配新版本support库 · Issue #42 · elemers/HermesEventBus
HermesEventBusに対応させる
あとは、Activity、Serviceの中のEventBus
をHermesEventBus
に置き換えます。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
HermesEventBus.getDefault().post(new GreetEvent("Hello"));
}
}
public class MyService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
HermesEventBus.getDefault().register(this);
return super.onStartCommand(intent, flags, startId);
}
...
}
こんなふうに単純に書き換えるだけです。
結果
今度は、Toastが表示されます。
別プロセスでも、Serviceに通知が届いていることが確認できたかと思います。
まとめ
EventButを使った既存のアプリで、Serviceを別プロセスで動かすことになっても、BroadcastReceiverなどを使うよりかは変更する手間は省けます。
もし、どうしても別プロセスで動かさなければならなくなったときは、便利なライブラリですね。