EventBus源码解析一

目录

0、相关文章:

1、EventBus概述

1.1、两种概述

1.1.1、概述一

1.1.2、概述二

1.2、常见的组件间通信方式

1.3、思考

1.3.1、一种思路:

1.3.2、EventBus的优点

2、使用

2.1、引入依赖:

2.2、使用:

3、自己手写一个EventBus

3.1、GsEventBus.java

3.2、GsSubscribe

3.3、GsSubscribeMethod.java

3.4、GsThreadMode

3.5、EventBusTest4Activity.java

3.6、EventBusTest5Activity.java


0、相关文章:

官网:http://greenrobot.org/eventbus/

EventBus官方教程

视频:https://study.163.com/course/courseLearn.htm?courseId=1209174836#/learn/video?lessonId=1278769701&courseId=1209174836

手写EventBus框架——源码分析1(2017年写的,参照3.0版本)

1、EventBus概述

1.1、两种概述

1.1.1、概述一

图一:

1.1.2、概述二

图二:

EventBus除了可以在四大组件之间通信外,还可以在异步线程与主线程之间进行通信。

EventBus流程图(官网):

1.2、常见的组件间通信方式

  1. Intent
  2. Handler
  3. Interface
  4. BroadcastReceiver
  5. AIDL
  6. Messenger

1.3、思考

1.3.1、一种思路:

 

1.3.2、EventBus的优点

2、使用

2.1、引入依赖:

implementation 'org.greenrobot:eventbus:3.1.1'

2.2、使用:

/**
 * Created by songzi522 on 2019/12/9.
 * 定义事件
 */

public class MyBusEvent {
    public final String message;

    public MyBusEvent(String message) {
        this.message = message;
    }
}
public class EventBusTest3Activity extends AppCompatActivity {

    @BindView(R.id.btn1)
    Button btn1;
    @BindView(R.id.btn2)
    Button btn2;
    @BindView(R.id.btn3)
    Button btn3;
    @BindView(R.id.btn4)
    Button btn4;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_event_bus_test3);
        ButterKnife.bind(this);
    }

    @OnClick({R.id.btn1, R.id.btn2, R.id.btn3, R.id.btn4})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.btn1:
                EventBus.getDefault().postSticky(new MyBusEvent("Hello Android"));
                break;
            case R.id.btn2:
                break;
            case R.id.btn3:
                break;
            case R.id.btn4:
                break;
        }
    }

    // EventBus 的注册与注销最好与Activity和Fragment的生命周期绑定
    @Override
    protected void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        EventBus.getDefault().unregister(this);
    }

    // 订阅 事件  准备订阅者
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(MyBusEvent event) {
        SmartToast.show(event.message);
    }


}

3、自己手写一个EventBus

3.1、GsEventBus.java

/**
 * Created by songzi522 on 2019/12/11.
 * 自己手写一个 EventBus
 * 该类可以理解为一个专门负责管理 需要传递的事件 的管理类
 * Activity1(事件发送方)把事件传递给 GsEventBus
 * Activity2(事件接收方)把接受事件传递的方法传给 GsEventBus
 * 所有的事情都由 GsEventBus 来处理,与 Activity1 和 Activity2 无关
 * 因此,第一,GsEventBus 得是一个单例模式
 */

public class GsEventBus {

    //定义一个用来装方法的容器
    private Map<Object, List<GsSubscribeMethod>> cacheMap;

    private static volatile GsEventBus instance;

    // 用来切换线程
    private Handler mHandler;

    private GsEventBus() {
        cacheMap = new HashMap<>();
        mHandler = new Handler();
    }

    public static GsEventBus getDefault() {
        if (instance == null) {
            synchronized (GsEventBus.class) {
                if (instance == null) {
                    instance = new GsEventBus();
                }
            }
        }
        return instance;
    }

    /**
     * 当我们调用 register 方法的时候,就把接收消息的方法放到 cacheMap 中
     *
     * @param object
     */
    public void register(Object object) {
        List<GsSubscribeMethod> list = cacheMap.get(object);
        if (list == null) {
            list = findGsSubscribeMethods(object);
            cacheMap.put(object, list);
        }
    }

    private List<GsSubscribeMethod> findGsSubscribeMethods(Object object) {
        List<GsSubscribeMethod> list = new ArrayList<>();
        //获取 activity
        Class<?> clazz = object.getClass();

        // 除了获取当前activity的有添加注解的方法,它的父类中如果有添加注解的方法,也要放进list
        while (clazz != null) {
            // 过滤作用:凡是系统级别的父类,直接省略
            String name = clazz.getName();
            if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) {
                break;
            }

            //获取 activity 中的所有方法
            Method[] methods = clazz.getDeclaredMethods();
            for (Method method : methods) {
                //找到带有 GsSubscribe 的方法
                GsSubscribe gsSubscribe = method.getAnnotation(GsSubscribe.class);
                //如果为空,我们就继续寻找下一个
                if (gsSubscribe == null) {
                    continue;
                }
                //如果找到的话,我们就判断带有 GsSubscribe 注解的方法中的参数类型
                Class<?>[] types = method.getParameterTypes();
                //用以限制 传递事件的方法有且只有一个参数
                if (types.length != 1) {
                    LogUtils.e("GsEventBus only accept one parameter");
                }
                // 判断线程类型
                GsThreadMode gsThreadMode = gsSubscribe.gsThreadMode();
                // 封装
                GsSubscribeMethod gsSubscribeMethod = new GsSubscribeMethod(method, gsThreadMode, types[0]);
                list.add(gsSubscribeMethod);
            }
            // 转到当前activity的父类中
            clazz = clazz.getSuperclass();
        }
        return list;
    }

    public void unRegister(Object object) {

    }

    public void post(Object type) {
        //直接循环 cacheMap,然后找到对应的方法进行回调
        Set<Object> set = cacheMap.keySet();
        Iterator<Object> iterator = set.iterator();
        while (iterator.hasNext()) {
            Object object = iterator.next();
            //找到对应的activity中的含有注解的方法列表
            List<GsSubscribeMethod> list = cacheMap.get(object);
            for (GsSubscribeMethod gsSubscribeMethod : list) {
                // 比对 post传递的参数对象与接收信息的方法的参数对象是否相同
                if (gsSubscribeMethod.getType().isAssignableFrom(type.getClass())) {
                    // 判断在哪个线程
                    switch (gsSubscribeMethod.getmGsThreadMode()) {
                        case MAIN:
                            // 主线程 --> 主线程
                            if (Looper.myLooper() == Looper.getMainLooper()) {
                                invoke(gsSubscribeMethod, object, type);
                            }else { // 子线程 --> 主线程
                                mHandler.post(() ->
                                        invoke(gsSubscribeMethod, object, type));
                            }

                            break;
                        case BACKGRUOND:
                            // 主线程 --> 子线程
                            // 子线程 --> 子线程
                            break;
                    }

                }
            }
        }
    }

    private void invoke(GsSubscribeMethod gsSubscribeMethod, Object object, Object type) {
        Method method = gsSubscribeMethod.getmMethod();
        try {
            method.invoke(object, type);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }

}

3.2、GsSubscribe

/**
 * Created by songzi522 on 2019/12/11.
 * 注解类,作用:一个标记,它标记的方法都将被GsEventBus收录
 */
// 表示注解的是一个方法
@Target(ElementType.METHOD)
// 表示它是运行时的注解
@Retention(RetentionPolicy.RUNTIME)
public @interface GsSubscribe {

    GsThreadMode gsThreadMode() default GsThreadMode.MAIN;

}

3.3、GsSubscribeMethod.java

/**
 * Created by songzi522 on 2019/12/11.
 * 用来封装需要 GsEventBus 保存的方法
 */

public class GsSubscribeMethod {

    //回调方法
    private Method mMethod;

    //线程模式
    private GsThreadMode mGsThreadMode;

    //回调方法中的参数类型
    private Class<?> type;

    public GsSubscribeMethod(Method mMethod, GsThreadMode mGsThreadMode, Class<?> type) {
        this.mMethod = mMethod;
        this.mGsThreadMode = mGsThreadMode;
        this.type = type;
    }

    public Method getmMethod() {
        return mMethod;
    }

    public void setmMethod(Method mMethod) {
        this.mMethod = mMethod;
    }

    public GsThreadMode getmGsThreadMode() {
        return mGsThreadMode;
    }

    public void setmGsThreadMode(GsThreadMode mGsThreadMode) {
        this.mGsThreadMode = mGsThreadMode;
    }

    public Class<?> getType() {
        return type;
    }

    public void setType(Class<?> type) {
        this.type = type;
    }
}

3.4、GsThreadMode

/**
 * Created by songzi522 on 2019/12/11.
 * 一个枚举类,它代表EventBus通过post发送消息时,接收的线程是在主线程还是子线程
 */

public enum  GsThreadMode {

    MAIN,
    BACKGRUOND
}

3.5、EventBusTest4Activity.java

/**
 * 用来测试自己手写的 EventBus:GsEventBus
 */
public class EventBusTest4Activity extends BaseActivity {

    @BindView(R.id.tvMessage)
    TextView tvMessage;
    @BindView(R.id.btn1)
    Button btn1;
    @BindView(R.id.btn2)
    Button btn2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_event_bus_test4);
        ButterKnife.bind(this);

        GsEventBus.getDefault().register(this);
    }

    @OnClick({R.id.btn1, R.id.btn2})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.btn1:
                readyGo(EventBusTest5Activity.class);
                break;
            case R.id.btn2:
                break;
        }
    }

    //GsSubscribe 是个注解,它的作用是:只是一个标记,它标记的方法都将被 GsEventBus 收录
    //GsThreadMode:一个枚举类,它代表 GsEventBus 通过post发送消息时,接收的线程是在主线程还是子线程
    @GsSubscribe(gsThreadMode = GsThreadMode.MAIN)
    public void getMessage(MyBusEvent event) {
        LogUtils.e(event.message);
        LogUtils.e("当前线程名字:" + Thread.currentThread().getName());
    }

}

3.6、EventBusTest5Activity.java

public class EventBusTest5Activity extends AppCompatActivity {

    @BindView(R.id.tvMessage)
    TextView tvMessage;
    @BindView(R.id.btn1)
    Button btn1;
    @BindView(R.id.btn2)
    Button btn2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_event_bus_test5);
        ButterKnife.bind(this);
    }

    @OnClick({R.id.btn1, R.id.btn2})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.btn1:
                //发送消息给 EventBusTest4Activity
//                GsEventBus.getDefault().post(new MyBusEvent("来自5的消息"));

                new Thread() {
                    @Override
                    public void run() {
                        super.run();
                        GsEventBus.getDefault().post(new MyBusEvent("来自5的消息"));
                        LogUtils.e("当前线程名字:" + Thread.currentThread().getName());
                    }
                }.start();

                break;
            case R.id.btn2:
                break;
        }
    }
}

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值