起初是看到了@亚运的帖子,初步了解和使用了EventBus包,让我感到很惊奇,他没有使用Handler,BroatCast就可以自由的传递消息。@鸿洋大神提到他包含四个部分,订阅者、发布者、事件、总线。下面将一一做简单解释;
先贴一下最简单的EventBus使用的代码:
在OnCreate中有一行EventBus.getDefault().register(this);这里是注册EventBus,所传的参数为当前类实例。也就是事件的订阅;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);//注册
initView();
}
在OnDstroy中注销注册的EventBus,EventBus.getDefault().unregister(this);这也就是事件的取消订阅;
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
EventBus.getDefault().unregister(this);//注销
}
在点击事件中发送要传递的值,传递最简单字符串,也就是事件的发布;
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v.getId()==R.id.btn){
EventBus.getDefault().post("传的值");
}
}
此方法用于接收事件发布者发送或者说传递的值,为什么这个方法名要写成onEvent...这个后面会做解释;
public void onEventMainThread(String str){
text.setText(str);
}
所有代码就这么多,这么简单易懂,这也是我写这个帖子的初衷,就是简单易懂,仅此而已。在这段简单的代码中我们没有看到Handler,没有看到广播,而且在主线程(UI线程)中更新了UI。
下面我们解释一下大家的一点:
首先是注册:EventBus.getDefault().register(this);
已公布的注册方法有四个:
public void register(Object subscriber) {
register(subscriber, DEFAULT_METHOD_NAME, false, 0);
}
public void register(Object subscriber, int priority) {
register(subscriber, DEFAULT_METHOD_NAME, false, priority);
}
public void registerSticky(Object subscriber) {
register(subscriber, DEFAULT_METHOD_NAME, true, 0);
}
public void registerSticky(Object subscriber, int priority) {
register(subscriber, DEFAULT_METHOD_NAME, true, priority);
}
细心的朋友可以看到他们都调用了一个方法:
private synchronized void register(Object subscriber, String methodName, boolean sticky, int priority) {
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass(),
methodName);
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod, sticky, priority);
}
}
四个参数
subscriber 是我们扫描类的对象,也就是我们代码中常见的this;
methodName 这个是写死的:“onEvent”,用于确定扫描什么开头的方法,可见我们的类中都是以这个开头。
sticky 这个参数,解释源码的时候解释,暂时不用管
priority 优先级,优先级越高,在调用的时候会越先调用。
看到其源码部分你会发现,首先它会得到这类的所有的方法,然后去遍历每一个方法,分别判断了是否以onEvent开头,是否是public且非static和abstract方法,是否是一个参数。如果都复合,才进入封装的部分。当符合要求的时候就会封装到一个Map中,Map的键就是类类型Class类型,而值就是onEvent开头的方法中的参数类型,在给出的代码中就是String,这个String类型为以后的Post方法埋下伏笔。
那么很多同学一定对 onEventMainThread中onEvent后面为什么是MainThread感兴趣,看了一下几行源码应该就懂了:
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case PostThread:
invokeSubscriber(subscription, event);
break;
case MainThread:
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
break;
case BackgroundThread:
if (isMainThread) {
backgroundPoster.enqueue(subscription, event);
} else {
invokeSubscriber(subscription, event);
}
break;
case Async:
asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
具体的解释请点击:http://blog.csdn.net/lmj623565791/article/details/40920453
下面说一下Post函数EventBus.getDefault().post("传的值");
我这里为了通俗易懂,写的特别的low,大家见谅。
那么是怎么onEventMainThread方法是怎么知道有人给他传递了一个字符串的呢?大家还记得注册后封装的Map吗?Map<Class,String>,其实最后的Map应该是这样的Map<Class , Map<MethodName , ValueType>>,首先根据注册的类名找到onEvent方法名和数值类型的Map,然后根据Post的数据类型找到对应的onEvent方法,所以onEventMainThread就能够接收到所传递的值了。
好奇心比较浓的朋友一定在想,内部究竟是怎么轮询onEvent方法?究竟是怎么发送给UI线程Post过来的值的?
算了还是解释一下onEvent方法吧,我这里只说一下MainThread:
case MainThread:
首先去判断当前如果是UI线程,则直接调用;否则: mainThreadPoster.enqueue(subscription, event);把当前的方法加入到队列,然后直接通过handler去发送一个消息,在handler的handleMessage中,去执行我们的方法。说白了就是通过Handler去发送消息,然后执行的。
这是鸿洋大神的总结,说的比唱的都完美,大家这回懂了吧,依然是你熟悉的Handler只是被封装的完美无瑕。
就到这里吧,这是我的第二个帖子,我个人正处在玩命赚首付的阶段,时间有限,希望大家多多提出宝贵意见,我会一一回答大家的建议和疑问的,下节应该会写Android空间数据库Spatialite的帖子。
最后在这里感谢亚运同学和鸿洋大神!!