web-dev-qa-db-ja.com

より効率的なブロードキャストレシーバーまたはハンドラーとは何ですか?

BroadcastレシーバーのonReceive()とHandlerのhandleMessage()が同じUIスレッドで実行されることを知っています。同じアプリ(プロセス)内で、2つのサービス間で通信したいとします。放送受信機クラスを拡張してイベントを登録できます

OR

ハンドラーを作成し、そのインスタンスを他のサービスに渡して、sendMessage()呼び出しに使用します。どちらの場合も、新しいスイッチケースを追加する必要があります。しかし、どちらのアプローチがより効率的ですか?コードがスレッドセーフである(UIの更新がない)と仮定しましょう。

15
Rohit Rokde

放送受信機クラスを拡張してイベントを登録できます

LocalBroadcastManagerを介してこれを行っていることを意味する場合(詳細については Kapeller氏の優れた回答 を参照)、HandlerLocalBroadcastManagerHandlerを使用します。ただし、パフォーマンスの違いは問題になるほど十分ではありません。同じことが、greenrobotのEventBusやSquareのOttoなどの他のインプロセスイベントバスの実装にも当てはまります。すべてが十分に高速であるため、保守性などの他の懸念事項が最優先されます。

システムブロードキャスト(たとえば、Contextで呼び出されるsendBroadcast())を介してこれを実行している場合は、HandlerLocalBroadcastManager、またはその他のイベントバスの実装は大幅に高速化され、安全性も向上します。

これはすべて、2つのサービスが同じプロセスにあることを前提としています。

すべての中で最速の解決策は、2つのサービスを1つに結合することです。それらが同じ寿命を持っている場合、これは特に当てはまります。アプリに2つ以上のサービスを含めることが合理的である場合はたくさんありますが、明確な理由がない限り、独立した小さなサービスをたくさん作成しないでください。

23
CommonsWare

自分のアプリ内でActivitiesServicesの間の通信に通常のブロードキャストを使用しないでください。代わりにローカル放送を使用する必要があります!まず、通常のブロードキャストのように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);
_
26
Xaver Kapeller

ブロードキャストレシーバーコールは重い操作であり、イベントが複数回ブロードキャストされるとANRを取得する可能性があります。また、ブロードキャストレシーバーのonReceive()で取得するコンテキストは、アプリケーションコンテキストを取得するまで使用が制限されます。

対照的に、ハンドラー呼び出しは単純で異なるスレッドで実行され、ハンドラー呼び出しを開始するためにコンテキストが必要ないため、効率的です。 2つのサービスまたはアクティビティまたは2つのスレッド間の通信は、ハンドラーを使用して簡単に処理できます。他のすべての方法、つまりインテントとバウンドサービスは、メッセージパッシングのために内部的にハンドラーを使用します。

2
Nishanth Kumar