EventBus原理解析及手写框架

带你分析EventBus源码,用最少得代码实现EventBus功能

Android 高级工程师进阶 ~ 网易云课堂 学习笔记

【直播主题】EventBus原理解析及手写框架
【直播大纲】
1、组件间通信的常用方式,与实际项目的差距
2、用最少的代码实现EventBus功能,反射技术的运用
3、完成主线程、子线程任意的切换与调度

戳此链接占座:
https://url.163.com/QPF

EventBus 核心原理解析与实现

使用反射机制实现自定义EventBus

什么是EventBus ?

EventBus是Android和java的发布/订阅事件总线

事件总线是对发布-订阅模式的一种实现。它是一种集中式事件处理机制,允许不同的组件之间彼此通信
而又不需要相互依赖,达到解耦的目的。

常见的组件间通信方式

Intent
Handler
Interface
Broadcast 用于监听系统服务
Aidl 进程间通信
Messenger 进程间通信,Google 官方提供的api

EventBus 的优点

1,代码简单,快
2,jar包小,~50K
3,Activity ,Fragment以及线程间通信优秀
4,稳定,在1亿+应用得到实践

EventBus 实现步骤

1,创建线程模式
2,创建注解
3,封装方法类
4,“存储”方法,并通过反射进行调用

代码

package com.github.yoyozhangh.studydemo.eventbus;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class EventBus {

    private static volatile EventBus instance;

    private Map<Object, List<SubscribeMethod>> cacheMap;

    private static String TAG = EventBus.class.getSimpleName();

    private Handler mHandler;

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

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

    public void register(Object object) {
        List<SubscribeMethod> list = cacheMap.get(object);
        if (list == null) {
            list = findSubscribleMethods(object);
            cacheMap.put(object, list);
        }
    }

    private List<SubscribeMethod> findSubscribleMethods(Object object) {
        List<SubscribeMethod> list = new ArrayList<>();
        Class<?> clazz = object.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) {
                //找到带有SubScribe 注解的方法
                Subscribe subscribe = method.getAnnotation(Subscribe.class);
                if (subscribe == null) {
                    continue;
                }
                //判断带有Subscribe 注解方法中的参数类型
                Class<?>[] types = method.getParameterTypes();
                if (types.length != 1) {
                    Log.e("错误", "EventBus only accept one paramer ");
                }
                ThreadMode threadMode = subscribe.threadMode();

                SubscribeMethod subscribeMethod = new SubscribeMethod(method, threadMode, types[0]);
                list.add(subscribeMethod);
            }

            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<SubscribeMethod> list = cacheMap.get(obj);
            for (final SubscribeMethod subscribeMethod : list) {

                //a(if 条件前面的对象) 对象所对应的类信息是不是 b (if 条件后面的对象)对应所对应的类信息的父类或接口
                if (subscribeMethod.getType().isAssignableFrom(type.getClass())) {

                    switch (subscribeMethod.getmThreadMode()) {
                        case MAIN:
                            // 主 --- 主
                            if (Looper.myLooper() == Looper.getMainLooper()) {
                                invoke(subscribeMethod, obj, type);
                            } else {
                                mHandler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        invoke(subscribeMethod, obj, type);
                                    }
                                });
                            }

                            // 子 --- 主
                            break;
                        case BACKGROUND:
                            //ExecutorService 从主线程到子线程的切换
                            break;
                    }

//                    invoke(subscribeMethod, obj, type);
                }
            }
        }
    }

    private void invoke(SubscribeMethod subscribeMethod, Object obj, Object type) {
        Method method = subscribeMethod.getmMethod();
        try {
            method.invoke(obj, type);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public void unregister(Object object) {
        // TODO: 2019/6/15  
    }
}

package com.github.yoyozhangh.studydemo.eventbus;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Subscribe {

    ThreadMode threadMode() default ThreadMode.MAIN;
}

package com.github.yoyozhangh.studydemo.eventbus;

import java.lang.reflect.Method;

public class SubscribeMethod {

    //回调方法
    private Method mMethod;

    //线程模式
    private ThreadMode mThreadMode;

    //方法中的参数
    private Class<?> type;

    public Method getmMethod() {
        return mMethod;
    }

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

    public ThreadMode getmThreadMode() {
        return mThreadMode;
    }

    public void setmThreadMode(ThreadMode mThreadMode) {
        this.mThreadMode = mThreadMode;
    }

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

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


    public SubscribeMethod(Method mMethod, ThreadMode mThreadMode, Class<?> type) {
        this.mMethod = mMethod;
        this.mThreadMode = mThreadMode;
        this.type = type;
    }
}

package com.github.yoyozhangh.studydemo.eventbus;

public enum ThreadMode {

    MAIN,
    BACKGROUND
}

源码地址

https://github.com/yoyo0316/StudyDemo/commit/ec52c18c69f294f9d5419e34cacf42909a7b30bd

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值