当我们进行项目开发的时候,往往是需要应用程序的各组件、组件与后台线程间进行通信,比如在子线程中进行请求数据,当数据请求完毕后通过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,操作更方便哦

posted on 2019-09-10 14:16  xuxianyu  阅读(302)  评论(0编辑  收藏  举报