| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> EventBus 源码解析及使用体验,1个月学会Android开发 -> 正文阅读 |
|
[移动开发]EventBus 源码解析及使用体验,1个月学会Android开发 |
既然register了,那么肯定得说怎么调用是吧。 ? EventBus.getDefault().post(param); 调用很简单,一句话,你也可以叫发布,只要把这个param发布出去,EventBus会在它内部存储的方法中,进行扫描,找到参数匹配的,就使用反射进行调用。 现在有没有觉得,撇开专业术语:其实EventBus就是在内部存储了一堆onEvent开头的方法,然后post的时候,根据post传入的参数,去找到匹配的方法,反射调用之。 那么,我告诉你,它内部使用了Map进行存储,键就是参数的Class类型。知道是这个类型,那么你觉得根据post传入的参数进行查找还是个事么? 下面我们就去看看EventBus的register和post真面目。 2、register ========== EventBus.getDefault().register(this); 首先: EventBus.getDefault()其实就是个单例,和我们传统的getInstance一个意思: ? /* Convenience singleton for apps using a process-wide EventBus instance. / public static EventBus getDefault() { if (defaultInstance == null) { synchronized (EventBus.class) { if (defaultInstance == null) { defaultInstance = new EventBus(); } } } return defaultInstance; } 使用了双重判断的方式,防止并发的问题,还能极大的提高效率。 然后register应该是一个普通的方法,我们去看看: register公布给我们使用的有4个: ? public void register(Object subscriber) { register(subscriber, DEFAULT_METHOD_NAME, false, 0); } public void register(Object subscriber, int priority) { register(subscriber, DEFAULT_METHOD_NAME, false, priority); } public void registerSticky(Object subscriber) { register(subscriber, DEFAULT_METHOD_NAME, true, 0); } public void registerSticky(Object subscriber, int priority) { register(subscriber, DEFAULT_METHOD_NAME, true, priority); } 本质上就调用了同一个: ? private synchronized void register(Object subscriber, String methodName, boolean sticky, int priority) { List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass(), methodName); for (SubscriberMethod subscriberMethod : subscriberMethods) { subscribe(subscriber, subscriberMethod, sticky, priority); } } 四个参数 subscriber 是我们扫描类的对象,也就是我们代码中常见的this; methodName 这个是写死的:“onEvent”,用于确定扫描什么开头的方法,可见我们的类中都是以这个开头。 sticky 这个参数,解释源码的时候解释,暂时不用管 priority 优先级,优先级越高,在调用的时候会越先调用。 下面开始看代码: ? List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass(), methodName); 调用内部类SubscriberMethodFinder的findSubscriberMethods方法,传入了subscriber 的class,以及methodName,返回一个List。 那么不用说,肯定是去遍历该类内部所有方法,然后根据methodName去匹配,匹配成功的封装成SubscriberMethod,最后返回一个List。下面看代码: ? List findSubscriberMethods(Class 3、post ====== register完毕,知道了EventBus如何存储我们的方法了,下面看看post它又是如何调用我们的方法的。 再看源码之前,我们猜测下:register时,把方法存在subscriptionsByEventType;那么post肯定会去subscriptionsByEventType去取方法,然后调用。 下面看源码: ? /* Posts the given event to the event bus. / public void post(Ob
ject event) { PostingThreadState postingState = currentPostingThreadState.get(); List eventQueue = postingState.eventQueue; eventQueue.add(event); if (postingState.isPosting) { return; } else { postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper(); postingState.isPosting = true; if (postingState.canceled) { throw new EventBusException(“Internal error. Abort state was not reset”); } try { while (!eventQueue.isEmpty()) { postSingleEvent(eventQueue.remove(0), postingState); } } finally { postingState.isPosting = false; postingState.isMainThread = false; } } } currentPostingThreadState是一个ThreadLocal类型的,里面存储了PostingThreadState;PostingThreadState包含了一个eventQueue和一些标志位。 ? private final ThreadLocal currentPostingThreadState = new ThreadLocal() { @Override protected PostingThreadState initialValue() { return new PostingThreadState(); } } 把我们传入的event,保存到了当前线程中的一个变量PostingThreadState的eventQueue中。 10行:判断当前是否是UI线程。 16-18行:遍历队列中的所有的event,调用postSingleEvent(eventQueue.remove(0), postingState)方法。 这里大家会不会有疑问,每次post都会去调用整个队列么,那么不会造成方法多次调用么? 可以看到第7-8行,有个判断,就是防止该问题的,isPosting=true了,就不会往下走了。 下面看postSingleEvent ? private void postSingleEvent(Object event, PostingThreadState postingState) throws Error { Class 4、其余方法 ====== 介绍了register和post;大家获取还能想到一个词sticky,在register中,如何sticky为true,会去stickyEvents去查找事件,然后立即去post; 那么这个stickyEvents何时进行保存事件呢? 其实evevntbus中,除了post发布事件,还有一个方法也可以: ? public void postSticky(Object event) { synchronized (stickyEvents) { stickyEvents.put(event.getClass(), event); } // Should be posted after it is putted, in case the subscriber wants to remove immediately |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 7:50:19- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |