前篇分析了EventBus实现原理,今天就自己实现一下,代码比较简单清晰,比EventBus代码简单可以实现效果,就起名叫个EventCar
具体实现
1.实现注册
根据原理分析的步骤一样先从注册入手,其主要功能将接收数据的类和对应方法加入到缓存中:
//用于缓存接收数据的类(activity)和对应的方法 private Map<Object,List<SubscriberMethod>> cacheMap;
/** * 接受数据的类注册 * @param object 接受数据的activity */ public void register(Object object){ List<SubscriberMethod> list=cacheMap.get(object); if(list==null){ List<SubscriberMethod> methods = findSubscriberMethods(object); cacheMap.put(object,methods); } }
private List<SubscriberMethod> findSubscriberMethods(Object object) { List<SubscriberMethod> list=new CopyOnWriteArrayList<>(); Class<?> clazz=object.getClass(); Method[] methods = clazz.getMethods(); //循环查找包括父类的方法 while (clazz!=null){ String className=clazz.getName(); //父类如为系统类则停止 if(className.startsWith("java.")||className.startsWith("javax.")||className.startsWith("android.")){ break; } for (Method method:methods){ //含有注解的方法 Subscriber subscriber=method.getAnnotation(Subscriber.class); if(subscriber==null){ continue; } Class<?>[] parametersClazz = method.getParameterTypes(); if(parametersClazz.length!=1){ throw new RuntimeException("eventBus must be one parameter"); } Class<?> parameterClazz = parametersClazz[0]; SubscriberMethod subscriberMethod=new SubscriberMethod(method,subscriber.value(),parameterClazz); list.add(subscriberMethod); } clazz=clazz.getSuperclass(); } return list; }
以上代码是查找所定义的Subscriber注解方法,并加入缓存中,SubscriberMethod是用于封装查找的注解方法的一个model
2.发送数据
发送的数据需与接收方法的参数类型保持一致,发送主要就是在缓存中找到含有注解的类,并匹配数据类型对应的:
/** * 发送数据 * @param object 发送的数据 */ public void post(final Object object){ Class<?> parameterClazz = object.getClass(); Set<Object> keyCache = cacheMap.keySet(); Iterator<Object> it=keyCache.iterator(); while (it.hasNext()){ final Object activity=it.next(); List<SubscriberMethod> list = cacheMap.get(activity); for (final SubscriberMethod subscriberMethod:list){ if(subscriberMethod.getEventType().isAssignableFrom(parameterClazz)){ switch (subscriberMethod.getThreadMode()){ case PostThread: invoke(activity,subscriberMethod,object); break; case MainThread: if(Looper.myLooper()==Looper.getMainLooper()){ invoke(activity,subscriberMethod,object); }else { handler.post(new Runnable() { @Override public void run() { invoke(activity,subscriberMethod,object); } }); } break; case BackgroundThread: if(Looper.myLooper()!=Looper.getMainLooper()){ invoke(activity,subscriberMethod,object); }else { executorService.execute(new Runnable() { @Override public void run() { invoke(activity,subscriberMethod,object); } }); } break; } } } } } //传递参数到对应方法 private void invoke(Object activity, SubscriberMethod subscriberMethod, Object object) { try { subscriberMethod.getMethod().invoke(activity,object); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }
3.解除注册
核心代码就结束了,很简单的实现,最后在暴露出一个解除注册的方法就ok了:
public void unregister(Object object){ if(cacheMap.containsKey(object)) cacheMap.remove(object); }
具体使用
1.接收数据者
private TextView tvContent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvContent=findViewById(R.id.tvContent); EventCar.getDefault().register(this); }
@Subscriber(ThreadMode.PostThread) void reciever(User user){ tvContent.setText(user.toString()); }
@Override protected void onDestroy() { super.onDestroy(); EventCar.getDefault().unregister(this); }
2.发送数据者
EventCar.getDefault().post(new User("1","张三",45,new Date()));
PS: 注意接收的数据类型要和发送的数据类型保持一致
最后附上github源码: