我知道广播接收器的onReceive()和Handler的handleMessage()在同一个UI线程上运行。假设我想在同一个app(进程)中的两个服务之间进行通信。我可以扩展广播接收器类并注册事件
OR
一个Handler,然后将其实例传递给另一个用于sendMessage()调用的服务。在这两种情况下,我都需要添加一些新的开关案例。但哪种方法更有效?让我们假设代码是线程安全的(没有UI更新)。
答案 0 :(得分:26)
您不应该使用普通广播在自己应用内的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
(通常在BroadcastReciever
注册onResume()
):
@Override
public void onResume() {
super.onResume();
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());
IntentFilter filter = new IntentFilter(ACTION_EXAMPLE);
manager.registerReceiver(this.receiver, filter);
}
请勿忘记稍后取消注册BroadcastReceiver
(onPause()
中):
@Override
public void onPause() {
super.onPause();
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());
manager.unregisterReceiver(this.receiver);
}
最后你可以发送这样的本地广播:
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());
manager.sendBroadcast(intent);
答案 1 :(得分:23)
我可以扩展广播接收器类并注册事件
如果您的意思是通过LocalBroadcastManager
执行此操作(请参阅Mr. Kapeller's excellent answer for details),Handler
会稍微提高效率,因为LocalBroadcastManager
使用Handler
。但是,性能差异不应该足够重要。其他进行中的事件总线实现也是如此,例如greenrobot的EventBus和Square的Otto。所有这些都应该足够快,以至于其他问题,例如可维护性,应该是最重要的。
如果您的意思是通过系统广播(例如,在sendBroadcast()
上调用Context
),那么Handler
,LocalBroadcastManager
或其他事件总线实现将会更快,更安全。
所有这些都假设这两个服务处于同一个过程中。
最快的解决方案是将两种服务合二为一。如果它们具有相同的寿命,则尤其如此。在很多情况下,应用程序中有2个以上的服务是合理的,但是如果没有明确的理由,不要创建大量独立的小服务。
答案 2 :(得分:2)
广播接收器呼叫是繁重的操作,如果事件被多次广播,则有机会获得ANR。而且,在获得应用程序上下文之前,你在广播接收器的onReceive()中获得的上下文使用有限。
相比之下,处理程序调用很有效,因为它们很简单并且在不同的线程中运行,并且不需要上下文来启动处理程序调用。可以使用处理程序轻松处理2个服务或活动之间的通信或2个线程。事实上所有其他方式即... Intents和Bound服务在内部使用处理程序来传递消息。