当我们进行项目开发的时候,往往是需要应用程序的各组件、组件与后台线程间进行通信,比如在子线程中进行请求数据,当数据请求完毕后通过Handler或者是广播通知UI,而两个Fragment之家可以通过Listener进行通信等等。当我们的项目越来越复杂,使用Intent、Handler、Broadcast进行模块间通信、模块与后台线程进行通信时,代码量大,而且高度耦合。
Event 事件。它可以是任意类型。
Subscriber 事件订阅者。在EventBus3.0之前我们必须定义以onEvent开头的那几个方法,分别是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe(),并且指定线程模型,默认是POSTING。
Publisher 事件的发布者。我们可以在任意线程里发布事件,一般情况下,使用EventBus.getDefault()就可以得到一个EventBus对象,然后再调用post(Object)方法即可。
自己从零开始写EventBus
创建EventBus
/创建Eventbus public static EventBus getDefault() { if(instance==null) { synchronized (EventBus.class){ if (instance==null) { instance=new EventBus(); } } } return instance; }
注册
//注册 public void register(Object obj) { List<SubscribleMethod> list =cachemap.get(obj); if(list==null) { list =findSubscribleMethod(obj); cachemap.put(obj,list); } }
通信之间的寻找通过注解的方法寻找,这里为默认方式
@Subcrible(threadMode= ThreadMode.MAIN)
、
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Subcrible {
ThreadMode threadMode() default ThreadMode.MAIN;
}
Subcrible的各种状态
package com.example.eventbus; import java.lang.reflect.Method; public class SubscribleMethod { //回调方法 private Method mMethod; //线程模式 private ThreadMode mthreadMode; //方法中的参数 private Class<?> type; public SubscribleMethod(Method mMethod, ThreadMode mthreadMode, Class<?> type) { this.mMethod = mMethod; this.mthreadMode = mthreadMode; this.type = type; } public void setmMethod(Method mMethod) { this.mMethod = mMethod; } public void setMthreadMode(ThreadMode mthreadMode) { this.mthreadMode = mthreadMode; } public Method getmMethod() { return mMethod; } public ThreadMode getMthreadMode() { return mthreadMode; } public Class<?> getType() { return type; } public void setType(Class<?> type) { this.type = type; } }
通信寻找注解的方法
private List<SubscribleMethod> findSubscribleMethod(Object obj) { List<SubscribleMethod> list=new ArrayList<>(); Class< ?> clazz =obj.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) { //找到带有Subcrible 注解的方法 Subcrible subcrible=method.getAnnotation(Subcrible.class); if (subcrible==null) { continue; } //判断subscrible 注解的方法中的参数类 Class<?>[] type= method.getParameterTypes(); if(type.length!=1) { Log.e("TAG", "eventBus only accept one para " ); } ThreadMode threadMode=subcrible.threadMode(); SubscribleMethod subscribleMethod=new SubscribleMethod(method,threadMode,type[0]); list.add(subscribleMethod); } clazz= clazz.getSuperclass(); } return list; } public void post(final Object type) { //直接循环 Map里的方法 ,找到相对得然后回调 Set<Object> set =cachemap.keySet(); Iterator<Object> iterator=set.iterator(); while (iterator.hasNext()) { final Object obj =iterator.next(); List<SubscribleMethod>list=cachemap.get(obj); for (final SubscribleMethod subscribleMethod:list){ //a(if 条件得对象)对象所对应得类信息是不是b if条件后面得对象对象所对应得接口或者父类 if (subscribleMethod.getType().isAssignableFrom(type.getClass())) { switch (subscribleMethod.getMthreadMode()) { case MAIN: //主线程 -主线程 if (Looper.myLooper()==Looper.getMainLooper()) { invoke(subscribleMethod,obj,type); } else { //子线程 -主线程 mHandler.post(new Runnable() { @Override public void run() { invoke(subscribleMethod,obj,type); } }); } break; } } } } } private void invoke(SubscribleMethod subscribleMethod, Object obj, Object type) { Method method=subscribleMethod.getmMethod(); try { method.invoke(obj,type); }catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }
运行起来的效果如下
这里是源码包分享
链接:https://pan.baidu.com/s/1CnTNCndQHizktb4e338BnA
提取码:vcvx
复制这段内容后打开百度网盘手机App,操作更方便哦