0
点赞
收藏
分享

微信扫一扫

Eventbus使用及手写

五殳师兄 2022-03-27 阅读 68
android

EventBus是一种用于Android的事件发布-订阅,在不相互依赖的情况下进行组件间的通信,降低耦合。


使用方式:
1.添加依赖 implementation("org.greenrobot:eventbus:3.3.1")
2.注册 EventBus.getDefault().register(this);
3.注销 EventBus.getDefault().unregister(this);
4.接收事件 
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(Message message) {}
5.发送消息
EventBus.getDefault().post(new Message());

注意:Eventbus无法跨进程。

手写EventBus框架

流程图:

 

 源码:

MyEventBus.java

/**
 * EventBus核心类
 */
public class MyEventBus {

    private static MyEventBus myEventBus;

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

    private Handler mHandler;

    // 没有核心线程,只有非核心线程,并且每个非核心线程空闲等待的时间为60s,采用SynchronousQueue队列。
    private ExecutorService mExecutorService;

    public MyEventBus() {
        mCacheMap = new HashMap<>();
        mHandler = new Handler(Looper.getMainLooper());
        mExecutorService = Executors.newCachedThreadPool();
    }

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

    // 注册
    public void register(Object subscribe) {
        // 获取缓存数据,判断是否已经注册
        List<SubscribeMethod> subscribeMethods = mCacheMap.get(subscribe);
        if (subscribeMethods != null) {
            return;
        }
        // 未注册,遍历该类及其父类(非系统父类)所有订阅方法集合
        subscribeMethods = getSubscribeMethods(subscribe);
        mCacheMap.put(subscribe, subscribeMethods);
    }

    private List<SubscribeMethod> getSubscribeMethods(Object subscribe) {
        List<SubscribeMethod> subscribeMethods = new ArrayList<>();
        Class<?> aClass = subscribe.getClass();
        // 遍历该类及其父类(非系统父类)所有订阅方法集合
        while (aClass != null) {
            // 判断该类是否是系统类
            String name = aClass.getName();
            if (name.startsWith("java.") || name.startsWith("javax.")
                    || name.startsWith("android.") || name.startsWith("androidx.")) {
                break;
            }
            // 获取类中的所有方法,包括私有的(private、protected、默认以及public)的方法
            Method[] methods = aClass.getDeclaredMethods();
            for (Method method : methods) {
                // 获取方法的MySubscribe注解
                MySubscribe annotation = method.getAnnotation(MySubscribe.class);
                if (annotation == null) {
                    continue;
                }
                // 获取方法的参数类型,EventBus规定参数只能为一个
                Class<?>[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length != 1) {
                    throw new RuntimeException("EventBus规定参数只能为一个");
                }
                SubscribeMethod subscribeMethod = new SubscribeMethod(method, annotation.threadMode(), parameterTypes[0]);
                subscribeMethods.add(subscribeMethod);
            }
            // 获取父类
            aClass = aClass.getSuperclass();
        }
        return subscribeMethods;
    }

    // 取消注册
    public void unregister(Object subscribe) {
        List<SubscribeMethod> subscribeMethods = mCacheMap.get(subscribe);
        if (subscribeMethods != null) {
            mCacheMap.remove(subscribe);
        }
    }

    // 发送
    public void post(Object object) {
        // 遍历cacheMap中的所有注册类
        Set<Object> objects = mCacheMap.keySet();
        Iterator<Object> iterator = objects.iterator();
        while (iterator.hasNext()) {
            Object subscribe = iterator.next();
            List<SubscribeMethod> subscribeMethods = mCacheMap.get(subscribe);
            // 遍历注册类中的所有订阅方法
            for (SubscribeMethod subscribeMethod : subscribeMethods) {
                // 判断方法的参数类型跟post的参数类型是否一致
                if (subscribeMethod.getEventType().isAssignableFrom(object.getClass())) {
                    switch (subscribeMethod.getMyThreadMode()) {
                        case POSTING:
                        case MAIN: // 接收的方法要在主线程执行
                            // 判断当前所在线程
                            if (Looper.myLooper() == Looper.getMainLooper()) {
                                // 当前在主线程,则直接调用
                                invoke(subscribeMethod, subscribe, object);
                            } else {
                                // 当前在子线程,这通过handler切换线程调用
                                mHandler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        invoke(subscribeMethod, subscribe, object);
                                    }
                                });
                            }
                            break;
                        case ASYNC: // 接收的方法要在子线程执行
                            // 判断当前所在线程
                            if (Looper.myLooper() == Looper.getMainLooper()) {
                                // 当前在主线程,则加入线程池调用
                                mExecutorService.execute(new Runnable() {
                                    @Override
                                    public void run() {
                                        invoke(subscribeMethod, subscribe, object);
                                    }
                                });
                            } else {
                                // 当前在子线程,则直接调用
                                invoke(subscribeMethod, subscribe, object);
                            }
                            break;
                    }


                }
            }
        }
    }

    private void invoke(SubscribeMethod subscribeMethod, Object subscribe, Object object) {
        Method method = subscribeMethod.getMethod();
        try {
            method.invoke(subscribe, object);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

MySubscribe.java

/**
 * EventBus注解类
 */
@Target(ElementType.METHOD) // 作用域方法
@Retention(RetentionPolicy.RUNTIME) // 运行时
public @interface MySubscribe {
    MyThreadMode threadMode() default MyThreadMode.POSTING;
}
MyThreadMode.java
public enum MyThreadMode {
    /**
     * 默认主线程
     */
    POSTING,

    /**
     * 主线程
     */
    MAIN,

    /**
     * 子线程
     */
    ASYNC
}
SubscribeMethod.java
/**
 * EventBus订阅方法类
 */
public class SubscribeMethod {
    // 注册的方法
    private Method method;
    // 线程类型
    private MyThreadMode myThreadMode;
    // 参数类型
    private Class<?> eventType;

    public SubscribeMethod(Method method, MyThreadMode myThreadMode, Class<?> eventType) {
        this.method = method;
        this.myThreadMode = myThreadMode;
        this.eventType = eventType;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    public MyThreadMode getMyThreadMode() {
        return myThreadMode;
    }

    public void setMyThreadMode(MyThreadMode myThreadMode) {
        this.myThreadMode = myThreadMode;
    }

    public Class<?> getEventType() {
        return eventType;
    }

    public void setEventType(Class<?> eventType) {
        this.eventType = eventType;
    }
}

使用:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

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


    @Override
    protected void onDestroy() {
        super.onDestroy();
        MyEventBus.getDefault().unregister(this);
    }

    @MySubscribe(threadMode = MyThreadMode.MAIN)
    public void onEvent(MyEventBean myEventBean) {
        Toast.makeText(MainActivity.this, myEventBean.getTitle() + " - " + myEventBean.getType(),
                Toast.LENGTH_LONG).show();
    }

    public void click(View view) {
        startActivity(new Intent(MainActivity.this, MainActivity2.class));
    }
}
public class MainActivity2 extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
    }

    public void post(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                MyEventBus.getDefault().post(new MyEventBean("MyEventBus", 1));
            }
        }).start();
    }
}

个人手记,有误请指出,感谢~

举报

相关推荐

0 条评论