根据EventBus原理实现数据传递

前篇分析了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源码:

EventCar

猜你喜欢

转载自blog.csdn.net/gf6873/article/details/79527029