16

I know that onReceive() of the Broadcast receiver and handleMessage() of Handler run on the same UI thread. Suppose I want to communicate between two services, within the same app (process) . I can extend a broadcast receiver class and register an event

OR

a Handler and then pass its instance to the other service to be used for sendMessage() calls. In both the cases I would need to add some new switch case. But which approach is more efficient ? Lets assume that the code is thread safe (no UI updations).

Rohit Rokde
  • 622
  • 2
  • 8
  • 16
  • 1
    Is your problem solved or do you need further assistance? Please don't forget to accept the answer which helped you most. – Xaver Kapeller Aug 12 '14 at 14:56

3 Answers3

27

You should not use normal broadcasts to communicate between Activities and Services inside of your own app. You should use local broadcasts instead! First you have to define a BroadcastReceiver like for normal broadcasts:

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())) {
            ...
        }  
    }
};

After that you can get the LocalBroadcastManager like this:

LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());

And you can register the BroadcastReceiver like this (normally you register a BroadcastReciever in onResume()):

@Override
public void onResume() {
    super.onResume();

    LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());
    IntentFilter filter = new IntentFilter(ACTION_EXAMPLE);
    manager.registerReceiver(this.receiver, filter);
}

Don't forget to unregister the BroadcastReceiver later on (in onPause()):

@Override
public void onPause() {
    super.onPause();

    LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());
    manager.unregisterReceiver(this.receiver);
}

And finally you can send local broadcasts like this:

LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());
manager.sendBroadcast(intent);
Xaver Kapeller
  • 49,491
  • 11
  • 98
  • 86
  • 1
    For sending local broadcasts, you probably want LocalBroadcastManager manager = LocalBroadcastManager.getInstance(this); – J Wang Mar 06 '16 at 06:50
  • @JWang that is exactly what I am saying in my answer. – Xaver Kapeller Mar 06 '16 at 13:46
  • 6
    Your answer is overall excellent. I am pointing out a typo that you made. The use case you describe is for communicating between a service and an activity. You used getActivity() when getting the LocalBroadcastMamager both while sending and receiving. Presumably, either sending or receiving should be from the service and you should use `this` rather than getActivity() in the service case. – J Wang Mar 06 '16 at 21:48
23

I can extend a broadcast receiver class and register an event

If you mean that you are doing this via LocalBroadcastManager (see Mr. Kapeller's excellent answer for details), Handler will be slightly more efficient, as LocalBroadcastManager uses a Handler. However, the performance difference should not be enough to matter. The same goes for other in-process event bus implementations, such as greenrobot's EventBus and Square's Otto. All should be fast enough that other concerns, such as maintainability, should be paramount.

If you mean that you are doing this via system broadcasts (e.g., sendBroadcast() called on a Context), then Handler, LocalBroadcastManager, or other event bus implementations will be significantly faster, and more secure as well.

All of this assumes that the two services are in the same process.

The fastest solution of all is to combine the two services into one. This is particularly true if they have the same lifespan. There are plenty of cases where having 2+ services in an app is reasonable, but don't create lots of independent little services without a clear reason to do so.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
3

Broadcast receiver calls are heavy operations and there are chances to get ANR's if an event is broadcasted for multiple times. And also the context you get in onReceive() of Broadcast receiver has limited usage until you get application context.

In contrast, handler calls are efficient as they are simple and runs in the different thread and no context is required to start a handler call. communicating between 2 services or activities or 2 threads can be easily handled using handler. Infact all the other ways viz.. Intents and Bound services use handlers internally for message passing.