前阵子看了 Mr Simple的博客,关于事件总线的,自己也跟着学了下
一、什么是EventBus
EventBus是一种基于事件发布与订阅模式的事件总线,实现了Activity、Fragment、Service组件或对象之间交互。让发布与订阅充分的解耦。
二、与Android其他事件传递的区别
Android传递方式包括Handler、BroadcastReceiver、Interface回调方式相比,它不需要像Handler一样通过回调进行通信,还需要考虑是否需要在子线程操作等问题。
三、流程图
注册接受者的简单流程图
发布事件的简单流程图
通俗的说:
订阅事件
1、在我们OnCreate的时候EventBus.getDefault().register(this)注册事件总线,EventBus会遍历当前
对象的所有方法把所有的OnEvent方法记录下来,以Map的方式记录下来,其中key为OnEvent的参数类型,即传递的对象,value为OnEvent的方法。OnCreate执行完成后OnEventMainThread方法就以键值的形式存放在EventBus里面。
发布事件
2、调用EventBus.getDefault().post(传递的对象),EventBus会根据传递的对象实参去查找总线Map里面对应的方法,找到了我们的onEventMainThread,最终调用反射去执行我们的方法。
四、以实时监控网络状态为例子
Activity注册事件总线
public class EventNetWorkActivity extends Activity {
private TextView mNetworkState;
NetWorkBroadCactReceiver receiver = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_network);
mNetworkState = (TextView) findViewById(R.id.id_network_state);
registerBroadcastReceiver();
EventBus.getDefault().register(this);
}
// 这里的参数必须要是Event,跟post的对应一致
public void onEventMainThread(NetEvent event) {
Log.i("网络状态onEventMainThread", "" + event.getConnectResult());
if (event.getConnectResult()) {
mNetworkState.setVisibility(View.GONE);
} else {
mNetworkState.setVisibility(View.VISIBLE);
}
}
public void registerBroadcastReceiver() {
IntentFilter intentfilter = new IntentFilter();
intentfilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
receiver = new NetWorkBroadCactReceiver();
registerReceiver(receiver, intentfilter);
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
EventBus.getDefault().unregister(this);
unregisterReceiver(receiver);
super.onDestroy();
}
}
注意:onEventMainThread里面的参数必须要是自定义的EventType,就是传递的对象,否则系统找不到该方法不会执行。
public class NetWorkBroadCactReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
boolean isConnected = NetUtils.isNetworkConnected(context);
System.out.println("网络状态:" + isConnected);
System.out.println("wifi状态:" + NetUtils.isWifiConnected(context));
System.out.println("移动网络状态:" + NetUtils.isMobileConnected(context));
System.out.println("网络连接类型:" + NetUtils.getConnectedType(context));
if (isConnected) {
Log.i("提交", isConnected+"");
<span style="color:#ff0000;">EventBus.getDefault().post(new NetEvent(true));</span>
} else {
<span style="color:#ff0000;">EventBus.getDefault().post(new NetEvent(false));</span>
}
}
}
五、订阅事件的四种方法
1、OnEvent :该事件在哪个线程发出,OnEvent就在那个线程执行,即发布事件和接收事件都在同一个线程,使用这个方法OnEvent不能执行耗时的任务,否则会阻塞主线程
2、OnEventMainThread:无论事件在那个线程发布,OnEventMainThread都在UI线程执行执行,接收线程就在UI线程运行,更新UI是在主线程,当然也不能执行耗时任务
3、OnEventMainThread:无论事件在那个线程发布,OnEventMainThread都在UI线程执行执行,接收线程就在UI线程运行,更新UI是在主线程,当然也不能执行耗时任务
4、onEventBackground:如果使用onEventBackgrond作为订阅函数,那么如果事件是在UI线程中发布出来的,那么onEventBackground就会在子线程中运行,如果事件本来就是子线程中发布出来的,那么onEventBackground函数直接在该子线程中执行。
5、onEventAsync:使用这个函数作为订阅函数,异步订阅,无论事件在哪个线程发布,都会创建新的子线程在执行onEventAsync.
public void onEvent(Object object)
{
Log.e("hongliang","onEvent");
}
本类发布本类订阅
public class ItemListFragment extends ListFragment {
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Register
EventBus.getDefault().register(this);
}
@Override
public void onDestroy()
{
super.onDestroy();
// Unregister
</span> EventBus.getDefault().unregister(this);<span style="color:#ff0000;">
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
// 开启线程加载列表
new Thread()
{
public void run()
{
try
{
Thread.sleep(2000); // 模拟延时
// 发布事件,在后台线程发的事件
EventBus.getDefault().post(new ItemListEvent(Item.ITEMS));
} catch (InterruptedException e)
{
e.printStackTrace();
}
};
}.start();
}
public void onEventMainThread(ItemListEvent event)
{
</span>setListAdapter(new ArrayAdapter<Item>(getActivity(),
android.R.layout.simple_list_item_activated_1,
android.R.id.text1, event.getItems())); <span style="color:#ff0000;">
}
@Override
public void onListItemClick(ListView listView, View view, int position,
long id)
{
super.onListItemClick(listView, view, position, id);
EventBus.getDefault().post(getListView().getItemAtPosition(position));
}
}