简单并快乐着,带有语法强类型检查的事件总线(EventBus)框架完善篇
在上一篇(http://blog.csdn.net/z13759561330/article/details/49467737)中提出一个改进的框架,之后小弟花了一点时间进行完善,代码其实很简单(相对于GreenRobot的EventBus来说):
package com.zjg.smart.android.app;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import android.os.Handler;
import android.os.Looper;
import com.zjg.smart.utils.DebugUtils;
public class EventBus {
// 采用泛型接口的好处是,篇译器自动帮你补全方法
// 如EventBus一样,四种模式的接收者接口
// 每种模式一个接口,按需实现
public interface EventReceiver<E> {
public void onEvent(E event);
}
public interface EventMainThreadReceiver<E> {
public void onEventMainThread(E event);
}
public interface EventBackgroundThreadReceiver<E> {
public void onEventBackgroundThread(E event);
}
public interface EventAsyncReceiver<E> {
public void onEventAsync(E event);
}
private static class SingletonHelper {
public static EventBus instance =new EventBus();
}
private EventBus() {
}
public static EventBus getInstance() {
return SingletonHelper.instance;
}
private HashMap<Class<?>, List<EventBus.EventReceiver<?>>>eventReceiverHashMap =new HashMap<Class<?>, List<EventBus.EventReceiver<?>>>();
private HashMap<Class<?>, List<EventBus.EventMainThreadReceiver<?>>>eventMainThreadReceiverHashMap =new HashMap<Class<?>, List<EventBus.EventMainThreadReceiver<?>>>();
private HashMap<Class<?>, List<EventBus.EventBackgroundThreadReceiver<?>>>eventBackgroundThreadReceiverHashMap =new HashMap<Class<?>, List<EventBus.EventBackgroundThreadReceiver<?>>>();
private HashMap<Class<?>, List<EventBus.EventAsyncReceiver<?>>>eventAsyncReceiverHashMap =new HashMap<Class<?>, List<EventBus.EventAsyncReceiver<?>>>();
// 订阅事件的方法,相应的有四种模式,这里篇译器自动对事件的类型进行检查
// 订阅者必须实现相应类型、相应模式的接收者接口,才能订阅相对应的事件
public <E>void registerEventReceiver(EventReceiver<E>receiver,
Class<E> cls) {
if (receiver ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "receiver ==null");
}
if (cls ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "cls == null");
}
List<EventBus.EventReceiver<?>> eventReceiverList = eventReceiverHashMap
.get(cls);
if (eventReceiverList ==null) {
eventReceiverList =new LinkedList<EventBus.EventReceiver<?>>();
eventReceiverHashMap.put(cls,eventReceiverList);
}
eventReceiverList.add(receiver);
}
public <E>void registerEventMainThreadReceiver(
EventMainThreadReceiver<E> receiver, Class<E> cls) {
if (receiver ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "receiver ==null");
}
if (cls ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "cls == null");
}
List<EventBus.EventMainThreadReceiver<?>> eventMainThreadReceiverList = eventMainThreadReceiverHashMap
.get(cls);
if (eventMainThreadReceiverList ==null) {
eventMainThreadReceiverList =new LinkedList<EventBus.EventMainThreadReceiver<?>>();
eventMainThreadReceiverHashMap
.put(cls, eventMainThreadReceiverList);
}
eventMainThreadReceiverList.add(receiver);
}
public <E>void registerEventBackgroundThreadReceiver(
EventBackgroundThreadReceiver<E> receiver, Class<E> cls) {
if (receiver ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "receiver ==null");
}
if (cls ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "cls == null");
}
List<EventBus.EventBackgroundThreadReceiver<?>> eventBackgroundThreadReceiverList = eventBackgroundThreadReceiverHashMap
.get(cls);
if (eventBackgroundThreadReceiverList ==null) {
eventBackgroundThreadReceiverList =new LinkedList<EventBus.EventBackgroundThreadReceiver<?>>();
eventBackgroundThreadReceiverHashMap.put(cls,
eventBackgroundThreadReceiverList);
}
eventBackgroundThreadReceiverList.add(receiver);
}
public <E>void registerAsyncReceiver(EventAsyncReceiver<E>receiver,
Class<E> cls) {
if (receiver ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "receiver ==null");
}
if (cls ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "cls == null");
}
List<EventBus.EventAsyncReceiver<?>> eventAsyncReceiverList = eventAsyncReceiverHashMap
.get(cls);
if (eventAsyncReceiverList ==null) {
eventAsyncReceiverList =new LinkedList<EventBus.EventAsyncReceiver<?>>();
eventAsyncReceiverHashMap.put(cls,eventAsyncReceiverList);
}
eventAsyncReceiverList.add(receiver);
}
// 退订事件,也是相应的四种模式
public <E>void unregisterEventReceiver(EventReceiver<E>receiver,
Class<E> cls) {
if (receiver ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "receiver ==null");
}
if (cls ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "cls == null");
}
List<EventBus.EventReceiver<?>> eventReceiverList = eventReceiverHashMap
.get(cls);
if (eventReceiverList !=null) {
eventReceiverList.remove(receiver);
}
}
public <E>void unregisterEventMainThreadReceiver(
EventMainThreadReceiver<E> receiver, Class<E> cls) {
if (receiver ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "receiver ==null");
}
if (cls ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "cls == null");
}
List<EventBus.EventMainThreadReceiver<?>> eventMainThreadReceiverList = eventMainThreadReceiverHashMap
.get(cls);
if (eventMainThreadReceiverList !=null) {
eventMainThreadReceiverList.remove(receiver);
}
}
public <E>void unregisterEventBackgroundThreadReceiver(
EventBackgroundThreadReceiver<E> receiver, Class<E> cls) {
if (receiver ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "receiver ==null");
}
if (cls ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "cls == null");
}
List<EventBus.EventBackgroundThreadReceiver<?>> eventBackgroundThreadReceiverList = eventBackgroundThreadReceiverHashMap
.get(cls);
if (eventBackgroundThreadReceiverList !=null) {
eventBackgroundThreadReceiverList.remove(receiver);
}
}
public <E>void unregisterAsyncReceiver(EventAsyncReceiver<E>receiver,
Class<E> cls) {
if (receiver ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "receiver ==null");
}
if (cls ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "cls == null");
}
List<EventBus.EventAsyncReceiver<?>> eventAsyncReceiverList = eventAsyncReceiverHashMap
.get(cls);
if (eventAsyncReceiverList !=null) {
eventAsyncReceiverList.remove(receiver);
}
}
// 事件发送方法,对事件的类型和模式都进行匹配
public <E>void post(final Eevent) {
if (event ==null) {
throw new NullPointerException(DebugUtils.STACK_TRACE()
+ "event == null");
}
List<EventReceiver<?>> eventReceiverList =eventReceiverHashMap
.get(event.getClass());
if (eventReceiverList !=null) {
for (inti = 0,sz =eventReceiverList.size();i < sz; i++) {
EventBus.EventReceiver<E> eventReceiver = (EventReceiver<E>)eventReceiverList
.get(i);
if (eventReceiver !=null) {
eventReceiver.onEvent(event);
}
}
}
List<EventMainThreadReceiver<?>> eventMainThreadReceiverList = eventMainThreadReceiverHashMap
.get(event.getClass());
if (eventMainThreadReceiverList !=null) {
for (inti = 0,sz =eventMainThreadReceiverList.size();i < sz; i++) {
final EventBus.EventMainThreadReceiver<E>eventMainThreadReceiver = (EventMainThreadReceiver<E>)eventMainThreadReceiverList
.get(i);
if (eventMainThreadReceiver !=null) {
if (Thread.currentThread() == Looper.getMainLooper()
.getThread()) {
// 如果当前线程是主线程,直接回调
eventMainThreadReceiver.onEventMainThread(event);
} else {
// 如果不是主线程,寄送到主线程回调
new Handler(Looper.getMainLooper())
.post(new Runnable() {
@Override
publicvoid run() {
//TODO自动生成的方法存根
eventMainThreadReceiver
.onEventMainThread(event);
}
});
}
}
}
}
List<EventBus.EventBackgroundThreadReceiver<?>> eventBackgroundThreadReceiverList = eventBackgroundThreadReceiverHashMap
.get(event.getClass());
if (eventBackgroundThreadReceiverList !=null) {
for (inti = 0,sz =eventBackgroundThreadReceiverList.size();i < sz; i++) {
final EventBus.EventBackgroundThreadReceiver<E>eventBackgroundThreadReceiver = (EventBackgroundThreadReceiver<E>)eventBackgroundThreadReceiverList
.get(i);
if (eventBackgroundThreadReceiver !=null) {
if (Thread.currentThread() != Looper.getMainLooper()
.getThread()) {
// 如果当前线程不是主线程,直接回调
eventBackgroundThreadReceiver
.onEventBackgroundThread(event);
} else {
// 如果当前线程是主线程,另开线程回调
new Thread() {
publicvoid run() {
eventBackgroundThreadReceiver
.onEventBackgroundThread(event);
};
}.start();
}
}
}
}
List<EventAsyncReceiver<?>> eventAsyncReceiverList =eventAsyncReceiverHashMap
.get(event.getClass());
if (eventAsyncReceiverList !=null) {
for (inti = 0,sz =eventAsyncReceiverList.size();i < sz; i++) {
final EventBus.EventAsyncReceiver<E>eventAsyncReceiver = (EventAsyncReceiver<E>)eventAsyncReceiverList
.get(i);
if (eventAsyncReceiver !=null) {
new Thread() {
publicvoid run() {
eventAsyncReceiver.onEventAsync(event);
}
}.start();
}
}
}
}
}
上例子,借用harvic880925的博客例程
(http://blog.csdn.net/harvic880925/article/details/40660137),在此表示感谢!
按照下面的步骤来建立这个工程:
从第一个Activity跳转到第二个Activity,从第二个Activity发送事件给第一个Activity。
MainActivity布局(activity_main.xml)
[html]view plaincopy
1. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
2. xmlns:tools="http://schemas.android.com/tools"
3. android:layout_width="match_parent"
4. android:layout_height="match_parent"
5. android:orientation="vertical">
6.
7. <Button
8. android:id="@+id/btn_try"
9. android:layout_width="match_parent"
10. android:layout_height="wrap_content"
11. android:text="btn_bty"/>
12. <TextView
13. android:id="@+id/tv"
14. android:layout_width="wrap_content"
15. android:layout_height="match_parent"/>
16.
17. </LinearLayout>
新建一个Activity,SecondActivity布局(activity_second.xml)
[html]view plaincopy
1. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
2. xmlns:tools="http://schemas.android.com/tools"
3. android:layout_width="match_parent"
4. android:layout_height="match_parent"
5. android:orientation="vertical"
6. tools:context="com.harvic.try_eventbus_1.SecondActivity">
7.
8. <Button
9. android:id="@+id/btn_first_event"
10. android:layout_width="match_parent"
11. android:layout_height="wrap_content"
12. android:text="First Event"/>
13.
14. </LinearLayout>
2、新建一个类FirstEvent,代表一种事件。
[java]view plaincopy
1. package com.harvic.other;
2.
3. publicclass FirstEvent {
4.
5. private String mMsg;
6. public FirstEvent(String msg) {
7. // TODO Auto-generatedconstructor stub
8. mMsg = msg;
9. }
10. public String getMsg(){
11. return mMsg;
12. }
13. }
这个类很简单,构造时传进去一个字符串,然后可以通过getMsg()获取出来。
3、在要接收事件的页面注册EventBus:
在上面的GIF图片的演示中,大家也可以看到,我们是要在MainActivity中接收发过来的事件,所以我们在MainActivity中订阅事件。
通常我们会在OnCreate()函数中订阅事件,在OnDestroy()函数中退订事件:
package com.zjg.eventbussample;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.zjg.smart.android.app.EventBus;
public class MainActivity extends Activityimplements
EventBus.EventMainThreadReceiver<FirstEvent> {
Button btn;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 订阅事件
EventBus.getInstance().registerEventMainThreadReceiver(this,
FirstEvent.class);
btn = (Button) findViewById(R.id.btn_try);
tv = (TextView) findViewById(R.id.tv);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated methodstub
Intent intent = new Intent(getApplicationContext(),
SecondActivity.class);
startActivity(intent);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this addsitems to the action bar if it is present.
getMenuInflater().inflate(R.menu.main,menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clickshere. The action bar will
// automatically handle clickson the Home/Up button, so long
// as you specify a parent activityin AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onEventMainThread(FirstEvent event) {
// TODO自动生成的方法存根
String msg = "onEventMainThread收到了事件:" +event.getMsg();
Log.d("harvic",msg);
tv.setText(msg);
Toast.makeText(this,msg, Toast.LENGTH_LONG).show();
}
@Override
protected void onResume() {
// TODO自动生成的方法存根
super.onResume();
}
@Override
protected void onDestroy() {
// TODO自动生成的方法存根
super.onDestroy();
EventBus.getInstance().unregisterEventMainThreadReceiver(this,
FirstEvent.class);
}
}
EventBus.getInstance().post(
new FirstEvent("FirstEvent btn clicked"));
完整的SecondActivity.java的代码如下:
package com.zjg.eventbussample;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import com.zjg.smart.android.app.EventBus;
public class SecondActivity extends Activity {
private Buttonbtn_FirstEvent;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO自动生成的方法存根
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
btn_FirstEvent = (Button) findViewById(R.id.btn_first_event);
btn_FirstEvent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated methodstub
EventBus.getInstance().post(
new FirstEvent("FirstEventbtn clicked"));
}
});
}
}
在MainActivity中重写onEventMainThread(FirstEvent event),参数就是我们自己定义的类:
在收到Event实例后,我们将其中携带的事件取出,一方面Toast出去,一方面传到TextView中;
@Override
public void onEventMainThread(FirstEvent event) {
// TODO自动生成的方法存根
String msg = "onEventMainThread收到了事件:" +event.getMsg();
Log.d("harvic",msg);
tv.setText(msg);
Toast.makeText(this,msg, Toast.LENGTH_LONG).show();
}
示例代码下载:http://download.csdn.net/detail/z13759561330/9222231