BroadcastレシーバーのonReceive()とHandlerのhandleMessage()が同じUIスレッドで実行されることを知っています。同じアプリ(プロセス)内で、2つのサービス間で通信したいとします。放送受信機クラスを拡張してイベントを登録できます
OR
ハンドラーを作成し、そのインスタンスを他のサービスに渡して、sendMessage()呼び出しに使用します。どちらの場合も、新しいスイッチケースを追加する必要があります。しかし、どちらのアプローチがより効率的ですか?コードがスレッドセーフである(UIの更新がない)と仮定しましょう。
放送受信機クラスを拡張してイベントを登録できます
LocalBroadcastManager
を介してこれを行っていることを意味する場合(詳細については Kapeller氏の優れた回答 を参照)、Handler
はLocalBroadcastManager
はHandler
を使用します。ただし、パフォーマンスの違いは問題になるほど十分ではありません。同じことが、greenrobotのEventBusやSquareのOttoなどの他のインプロセスイベントバスの実装にも当てはまります。すべてが十分に高速であるため、保守性などの他の懸念事項が最優先されます。
システムブロードキャスト(たとえば、Context
で呼び出されるsendBroadcast()
)を介してこれを実行している場合は、Handler
、LocalBroadcastManager
、またはその他のイベントバスの実装は大幅に高速化され、安全性も向上します。
これはすべて、2つのサービスが同じプロセスにあることを前提としています。
すべての中で最速の解決策は、2つのサービスを1つに結合することです。それらが同じ寿命を持っている場合、これは特に当てはまります。アプリに2つ以上のサービスを含めることが合理的である場合はたくさんありますが、明確な理由がない限り、独立した小さなサービスをたくさん作成しないでください。
自分のアプリ内でActivities
とServices
の間の通信に通常のブロードキャストを使用しないでください。代わりにローカル放送を使用する必要があります!まず、通常のブロードキャストのようにBroadcastReceiver
を定義する必要があります。
_private static final String ACTION_EXAMPLE = "ACTION_EXAMPLE";
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(ACTION_EXAMPLE.equals(intent.getAction())) {
...
}
}
};
_
その後、次のようにLocalBroadcastManager
を取得できます。
_LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());
_
そして、次のようにBroadcastReceiver
を登録できます(通常、onResume()
にBroadcastReciever
を登録します):
_@Override
public void onResume() {
super.onResume();
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());
IntentFilter filter = new IntentFilter(ACTION_EXAMPLE);
manager.registerReceiver(this.receiver, filter);
}
_
後で(onPause()
内で)BroadcastReceiver
の登録を解除することを忘れないでください。
_@Override
public void onPause() {
super.onPause();
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());
manager.unregisterReceiver(this.receiver);
}
_
そして最後に、次のようなローカルブロードキャストを送信できます。
_LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());
manager.sendBroadcast(intent);
_
ブロードキャストレシーバーコールは重い操作であり、イベントが複数回ブロードキャストされるとANRを取得する可能性があります。また、ブロードキャストレシーバーのonReceive()で取得するコンテキストは、アプリケーションコンテキストを取得するまで使用が制限されます。
対照的に、ハンドラー呼び出しは単純で異なるスレッドで実行され、ハンドラー呼び出しを開始するためにコンテキストが必要ないため、効率的です。 2つのサービスまたはアクティビティまたは2つのスレッド間の通信は、ハンドラーを使用して簡単に処理できます。他のすべての方法、つまりインテントとバウンドサービスは、メッセージパッシングのために内部的にハンドラーを使用します。