1、下面是EventBus3.0的一些用法和源码分析
<a href="http://www.jianshu.com/p/da9e193e8b03">EventBus使用详解</a>
<a href="http://www.jianshu.com/p/64e286b7e140">EventBus源码解析</a>
2、接下来自己实现EventBus的一些简单功能
定义一个EventBus类,主要实现register和post连个方法
public class EventBus {
private static volatile EventBus instace;
private Map<Object,List<SubscribleMethod>> eventTypesCache = new HashMap<>();
private EventBus(){
}
public static EventBus getDefault(){
if(instace == null){
synchronized (EventBus.class){
if(instace == null)
instace = new EventBus();
}
}
return instace;
}
public void register(Object subscriber){
List<SubscribleMethod> subscribleMethods = eventTypesCache.get(subscriber);
if(subscribleMethods == null){
subscribleMethods = findSubscriberMethods(subscriber);
eventTypesCache.put(subscriber,subscribleMethods);
}
}
private List<SubscribleMethod> findSubscriberMethods(Object subscriber) {
/**
* 线程安全
*/
List<SubscribleMethod> subscribleMethods = new CopyOnWriteArrayList<>();
Class<?> clazz = subscriber.getClass();
Method[] methods = clazz.getDeclaredMethods();
//循环查找父类的接受方法
while (clazz != null){
String name = clazz.getName();
if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) {
break;
}
for(Method method : methods){
Subscribe subscribe = method.getAnnotation(Subscribe.class);//拿到方法上的注解
if(subscribe == null){
continue;
}
//拿到方法的参数数组
Class<?>[] parameterTypes = method.getParameterTypes();
if(parameterTypes.length != 1)//如果方法中的参数不是一个,就抛错
throw new RuntimeException("eventBus must be one parameter!");
Class<?> parameterType = parameterTypes[0];
ThreadMode threadMode = subscribe.value();
SubscribleMethod subscribleMethod = new SubscribleMethod(method,threadMode,parameterType);
subscribleMethods.add(subscribleMethod);
}
clazz = clazz.getSuperclass();
}
return subscribleMethods;
}
public void post(Object event){
Set<Object> set = eventTypesCache.keySet();
Iterator<Object> iterator = set.iterator();
while (iterator.hasNext()){
Object subscriber = iterator.next();
List<SubscribleMethod> subscribleMethods = eventTypesCache.get(subscriber);
for(SubscribleMethod subscribleMethod :subscribleMethods){
if(subscribleMethod.getEventType().isAssignableFrom(event.getClass())){
invoke(subscriber,subscribleMethod,event);
}
}
}
}
private void invoke(Object subscriber,SubscribleMethod subscribleMethod,Object event){
try {
subscribleMethod.getMethod().invoke(subscriber,event);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
实现SubscribleMethod类,管理EventBus接受方法的一些属性,方法名、注解、参数
public class SubscribleMethod {
private Method method;//方法
private ThreadMode threadMode;//这个方法所在那个线程
private Class<?> eventType;//参数类型
public SubscribleMethod(Method method, ThreadMode threadMode, Class<?> eventType) {
this.method = method;
this.threadMode = threadMode;
this.eventType = eventType;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
public ThreadMode getThreadMode() {
return threadMode;
}
public void setThreadMode(ThreadMode threadMode) {
this.threadMode = threadMode;
}
public Class<?> getEventType() {
return eventType;
}
public void setEventType(Class<?> eventType) {
this.eventType = eventType;
}
}
定义一个ThreadMode枚举类主要是管理EventBus运行在线程的环境
public enum ThreadMode {
PostThread,
}
定义一个Subscribe注解类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Subscribe {
ThreadMode value() default ThreadMode.PostThread;
}
以上自己定义的EventBus已经完成简单的传递事件功能,
3、下面是使用自定义的EventBus
定义传递事件对象User
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
在第一个页面MainActivity中定义接受事件
@Subscribe
public void receive(User user){
tv.setText("姓名:"+user.getName()+",年龄:"+user.getAge());
}
在第二个页面发送事件
public void onSendDataClick(View view){
User user = new User();
user.setName("张三");
user.setAge(20);
EventBus.getDefault().post(user);
finish();
}
4、事件的效果如下:
5、接下来实现EventBus传递和接收事件的线程切换
在ThreadMode中添加几个枚举
public enum ThreadMode {
PostThread,
MainThread,
BackgroundThread,
}
在添加一个Handler和一个ExecutorService线程池的实例
private Handler handler;
private ExecutorService executorService;
private EventBus(){
handler = new Handler(Looper.getMainLooper());
executorService = Executors.newCachedThreadPool();
}
然后修改EventBus类的post方法
public void post(final Object event){
Set<Object> set = eventTypesCache.keySet();
Iterator<Object> iterator = set.iterator();
while (iterator.hasNext()){
final Object subscriber = iterator.next();
List<SubscribleMethod> subscribleMethods = eventTypesCache.get(subscriber);
for(final SubscribleMethod subscribleMethod :subscribleMethods){
if(subscribleMethod.getEventType().isAssignableFrom(event.getClass())){
//判断当前接受方法是在哪个线程
switch (subscribleMethod.getThreadMode()){
case PostThread:
invoke(subscriber,subscribleMethod,event);
break;
case MainThread://主线程
//判断发送线程是处在哪个线程 如果发送线程在主线程 则不需要线程切换 否则切换
if (Looper.myLooper() == Looper.getMainLooper()) {//在主线程
invoke(subscriber, subscribleMethod, event);
} else {//在子线程
handler.post(new Runnable() {
@Override
public void run() {
invoke(subscriber, subscribleMethod, event);
}
});
}
break;
case BackgroundThread://后台线程
//判断发送线程是处在哪个线程 如果发送线程是在子线程 则不需要切换 否则切换
if (Looper.getMainLooper() != Looper.myLooper()) {
//发生在子线程
invoke(subscriber, subscribleMethod, event);
} else {//主线程
executorService.execute(new Runnable() {
@Override
public void run() {
invoke(subscriber, subscribleMethod, event);
}
});
}
break;
}
}
}
}
}
最后在修改MainActivity中的接收事件注解
@Subscribe(ThreadMode.BackgroundThread)
public void receive(User user){
Log.e("zxj","Thread name:"+Thread.currentThread().getName());
tv.setText("姓名:"+user.getName()+",年龄:"+user.getAge());
}
ThreadMode的枚举是那个就对应在那个线程中
指定为MainThread时表示是在主线程,指定为BackgroundThread时表示是在子线程,当指定为PostThread(默认)时表示,发送事件(调用post方法)时,post在那个线程,接受就在那个线程
如下图当ThreadMode.BackgroundThread时:
<img src="http://upload-images.jianshu.io/upload_images/2918620-ad66abae11a6a3c9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/>
6、最后在提供一个取消注册的方法,在MainActivity的onDestroy方法中调用
public void unregister(Object subscriber) {
if (subscriber != null)
eventTypesCache.remove(subscriber);
}
到这里,自定义EventBus已经完成了,如有不对的地方还望指点。
<a href="http://download.csdn.net/detail/zuo1141783497/9861780">源码下载</a>