前言

Android EventBus这个知识点呢,我已经写了两篇文章,一篇是Android EventBus3.0使用详情,一篇是Android 浅谈EventBus源码,这两个篇文章讲了它的一个使用,还有源码解析,接下来我们通过自己写一个EventBus,让你更容易理解EventBus的原理,下面来看一看实现步骤

  1. 定义注解
  2. 定义线程模式
  3. 订阅方法封装成SubscribeMethod
  4. 写一个单例
  5. 封装订阅者方法
  6. 注册订阅者
  7. post发布事件
  8. 线程模式处理
  9. 执行订阅者方法
  10. 销毁注册

定义MySubscrible

首先我们定义一个MySubscrible注解,注解还不知道如何使用的,看我之前写的博客Android 注解(Annotation)的入门与使用(一)和Android 注解(Annotation)的入门与使用(二)

/** * QQ:941556675 * zhy * **/@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface MySubscrible {    ThreadMode threadMode() default ThreadMode.MAIN;}

定义线程模式

/** * QQ:941556675 * zhy * **/public enum  ThreadMode {    MAIN,    BACHGROUND}

订阅方法封装成SubscribeMethod

/** * QQ:941556675 * zhy * **/public class SubscribeMethod {    private Method method;    private ThreadMode threadMode;    //方法里面的参数类型    private Class<?> type;    public SubscribeMethod(Method method, ThreadMode threadMode, Class<?> type) {        this.method = method;        this.threadMode = threadMode;        this.type = type;    }    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<?> getType() {        return type;    }    public void setType(Class<?> type) {        this.type = type;    }}

写一个单例

/** * QQ:941556675 * zhy * **/public class MyEventBus {    private Handler mHandler;    static volatile MyEventBus defaultInstance;    private Map> map;    private ExecutorService executorService;    public static MyEventBus getDefault() {        MyEventBus instance = defaultInstance;        if (instance == null) {            synchronized (MyEventBus.class) {                instance = MyEventBus.defaultInstance;                if (instance == null) {                    instance = MyEventBus.defaultInstance = new MyEventBus();                }            }        }        return instance;    }    public MyEventBus(){     mHandler = new Handler();        map=new HashMap<>();        executorService = Executors.newCachedThreadPool();    } }

封装订阅者方法及注册订阅者

/** * QQ:941556675 * zhy * **/public void register(Object obj){        List subscribeMethods = map.get(obj);        if(subscribeMethods==null){            subscribeMethods = findSubscriberMethods(obj);            map.put(obj,subscribeMethods);        }    }    public List findSubscriberMethods(Object obj){        List list=new ArrayList<>();        Class<?> aClass = obj.getClass();        Method[] declaredMethods = aClass.getDeclaredMethods();        for(Method method:declaredMethods){        //判断该方法是否被MySubscrible注解了            if(method.isAnnotationPresent(MySubscrible.class)){             // 返回该方法的注解在此方法的指定注解类型                MySubscrible annotation = method.getAnnotation(MySubscrible.class);                 // 添加一些校验                Class<?>[] parameterTypes = method.getParameterTypes();                if(parameterTypes.length!=1){                    throw new RuntimeException("方法只能为一个参数");                }                ThreadMode threadMode = annotation.threadMode();                // 生成订阅者方法封装对象                SubscribeMethod methodManager = new SubscribeMethod(method, threadMode, parameterTypes[0]);                list.add(methodManager);            }        }        return list;    }

post发布事件

public void post(final Object obj){        Set objects = map.keySet();        for(final Object object:objects){            final List subscribeMethods = map.get(object);            if(subscribeMethods!=null&&subscribeMethods.size()>0){                    for(final SubscribeMethod subscribeMethod:subscribeMethods){// 判断发布者发布事件的发布的对象类型和订阅者方法的定义的类型是否一致                        if (subscribeMethod.getType().isAssignableFrom(obj.getClass())) {                           ...                        }                    }            }        }    }   

线程模式处理

if (subscribeMethod.getType().isAssignableFrom(obj.getClass())) {                            switch (subscribeMethod.getThreadMode()) { // 判断线程模式                                case MAIN:                                 // 判断当前线程是否是主线程                                    if(Looper.getMainLooper()==Looper.myLooper()){                                        invoke(subscribeMethod,object,obj);                                    }                                    else{                                    // 当前是子线程 handler 是用来切换到主线程的                                        mHandler.post(new Runnable() {                                            @Override                                            public void run() {                                                invoke(subscribeMethod,object,obj);                                            }                                        });                                    }                                    break;                                case BACHGROUND:                                 // 判断当前线程是否是主线程                                    if(Looper.getMainLooper()==Looper.myLooper()){                                    // 切换到子线程操作 executorService 是线程池对象                                        executorService.execute(new Runnable() {                                            @Override                                            public void run() {                                                invoke(subscribeMethod,object,obj);                                            }                                        });                                    }                                    else{                                    // 当前是子线程                                        invoke(subscribeMethod,object,obj);                                    }                                    break;                                 }                        }

执行订阅者方法

通过反射来执行订阅者方法

 private void invoke(SubscribeMethod methodManager, Object object, Object setter) {        Method method = methodManager.getMethod();        try {            // 通过反射执行方法            method.invoke(object, setter);        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (InvocationTargetException e) {            e.printStackTrace();        }    }

销毁注册

  public void unregister(Object object) {        if (object != null && map.get(object) != null && map.get(object).size() > 0) {            map.remove(object);        }    }

以上就是手写EventBus的步骤,接下来我们来看看如何使用

public class Test1 extends AppCompatActivity {    TextView btn;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.test);        btn= findViewById(R.id.btn);        MyEventBus.getDefault().register(this);        btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {               startActivity(new Intent(Test1.this,Test2.class));            }        });    }    @MySubscrible(threadMode =ThreadMode.MAIN)    public void test1(Cat cat){        Log.d(TAG, "ThreadMode.MAIN,发送过来数据是:" + cat.getName() + ",线程名:" + Thread.currentThread().getName());    } @MySubscrible(threadMode =ThreadMode.BACHGROUND)    public void test2(Cat cat){       Log.d(TAG, "ThreadMode.BACKGROUND,发送过来数据是:" + cat.getName() + ",线程名:" + Thread.currentThread().getName());    }    @Override    protected void onDestroy() {        super.onDestroy();        MyEventBus.getDefault().unregister(this);    }}
public class Test2 extends AppCompatActivity {    TextView btn;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.test);        btn= findViewById(R.id.btn);        btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {           send1();            }        });    }    public void send1(){        Log.d("Test2", "发布的线程:" + Thread.currentThread().getName());        Cat cat=new Cat();        cat.setName("猫咪:"+"主线程发布一个事件");        MyEventBus.getDefault().post(cat);    }    public void send2(){        new Thread(new Runnable() {            @Override            public void run() {                Log.d("Test2", "发布的线程:" + Thread.currentThread().getName());                Cat cat=new Cat();                cat.setName("猫咪:"+"子线程发布一个事件");                MyEventBus.getDefault().post(cat);            }        }).start();    }}

运行结果:

2018-08-26 07:29:08.330 14646-14646/cn.my.com.mywidget D/Test2: 发布的线程:main2018-08-26 07:29:08.331 14646-14646/cn.my.com.mywidget D/Test1: ThreadMode.MAIN,发送过来数据是:猫咪:主线程发布一个事件,线程名:main2018-08-26 07:29:08.334 14646-14711/cn.my.com.mywidget D/Test1: ThreadMode.BACKGROUND,发送过来数据是:猫咪:主线程发布一个事件,线程名:pool-1-thread-12018-08-26 07:31:57.245 14978-15039/cn.my.com.mywidget D/Test2: 发布的线程:Thread-22018-08-26 07:31:57.247 14978-15039/cn.my.com.mywidget D/Test1: ThreadMode.BACKGROUND,发送过来数据是:猫咪:子线程发布一个事件,线程名:Thread-22018-08-26 07:31:57.247 14978-14978/cn.my.com.mywidget D/Test1: ThreadMode.MAIN,发送过来数据是:猫咪:子线程发布一个事件,线程名:main

Demo地址

更多相关文章

  1. Android列表小部件(Widget)开发详解
  2. Android蓝牙API之BluetoothAdapter类(1)
  3. Android图像处理之Bitmap类
  4. [置顶] android 多线程Thread,Runnable,Handler,AsyncTask等之间
  5. Android解决在onCreate()中获取View的width、Height为0的方法
  6. Android(安卓)ADB 找不到设备的解决方法
  7. 初学Android,数据存储之SharedPreferences(四十一)
  8. android 预装第三方apk的方法(非system priv-app)
  9. Android(安卓)TextView使用HTML处理字体样式、显示图片等

随机推荐

  1. Android(安卓)Studio&Xcode常用快捷键整
  2. android枚举的替代(官方建议)
  3. 客户端相关知识学习(三)之Android原生与H5
  4. Android(安卓)HttpPost表单访问接口
  5. cordova学习四:事件Events
  6. Android(安卓)应用程序自动更新
  7. Android(安卓)SDK下载和更新失败的解决方
  8. Android(安卓)camera摄像头对焦,zoom的通
  9. android mediaplayer方法
  10. 基于Android的OpenGL—使用GLSurfaceView