博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
EventBus猜想 ----手把手带你自己实现一个EventBus
阅读量:5914 次
发布时间:2019-06-19

本文共 6732 字,大约阅读时间需要 22 分钟。

本文是什么

本文是一篇怀着推測角度学习一个未知东西(EventBus)的文章。

  1. 先推測EventBus是怎样实现的。
  2. 依据推測去模仿他的实现。
  3. 查看源代码。验证猜想。

    更深入的去理解他。

转载请注明出处:

关于EventBus前面已经介绍了他的使用方法。

依据使用流程猜想

使用EventBus的流程例如以下:

1. 注冊EventBus

EventBus.getDefault().register(this);

2 . 发送一条消息

EventBus.getDefault().post("hello eventBus");

3.处理这条消息

onEventMainThread()

原理猜想

也就是说,你想要接受一条消息,首先必需要先注冊。将本身作为參数传入EventBus。 然后你必须写一个onEvent方法。所以能够推測这里肯定是在post消息的时候 调用了这种方法,因为将本身传入了,所以这种方法能够用反射来调用。

猜想实现

呃。已经有了猜想,那么来实现下面我们这个步骤。

首先新建一个类。叫做EventBusLite。把他弄成单例模式

public class EventBusLite {    private static EventBusLite mEventBus;    private EventBusLite(){    }    public static EventBusLite getDefault(){        if(mEventBus == null){            mEventBus = new EventBusLite();        }        return mEventBus;    }}

然后。来模拟他的注冊方法。

public void register(Object obj){        mObj = obj;    }

就是简单的对象传參。

那么 如今在我们的Activity给他注冊一下:

public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); EventBusLite.getDefault().register(this); }}

此时。就注冊成功了。

然后来模拟他的Post方法。也就是发送消息方法。
事实上post方法是回调了MainActivity的onEvent()方法。模拟例如以下:

public void post(String str){        try {        //通过反射获取到这个类            Class clazz = mObj.getClass();            //获取到类的onEvent方法            Method method = clazz.getMethod("onEvent",String.class);            //运行这个实例的方法            method.invoke(mObj,str);        } catch (ClassNotFoundException e) {            e.printStackTrace();        } catch (NoSuchMethodException e) {            e.printStackTrace();        } catch (InvocationTargetException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        }    }

此时我们的post工作已经完毕。接下来仅仅需要写一个onEvent()方法就可以:

public void onEvent(String str){        Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();    }

在MainActivity增加一个button。监听里面发送消息:

@Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        EventBusLite.getDefault().register(this);        mButton = (Button) findViewById(R.id.btn);        mButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                EventBusLite.getDefault().post("hi");            }        });    }

运行效果例如以下:

这里写图片描写叙述

哈哈哈哈,猜想实践完毕。

如今,仅仅实现了postEvent模式:

在当前的线程运行。
那么其它onMainThread() onBackgroundThread()怎么实现呢?这里猜想为检查线程,然后使用handler。

验证猜想

接下来就是read the fxxking source code 的过程去验证我们的猜想。

首先看看注冊的方法,因为我的水平也不高。。也看不非常懂。

。所以这里就捡重点来看:

register调用了双參的

public void register(Object subscriber) {        register(subscriber, false, 0);    }

继续往下找。。

private synchronized void register(Object subscriber, boolean sticky, int priority) {        List
subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass()); for (SubscriberMethod subscriberMethod : subscriberMethods) { subscribe(subscriber, subscriberMethod, sticky, priority); } }

看到一个list 用来遍历寻找他这个类的方法。。

这里已经能够确定了是通过反射调用他的方法。

寻找方法的函数。。

List
findSubscriberMethods(Class
subscriberClass) {
//叽里呱啦一大堆。。。。。 while (clazz != null) { String name = clazz.getName(); if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) { //这里假设以这些包名开头,就会break。否则会减少性能 break; } //叽里呱啦一大堆....//然后是裁剪字符串,ON_EVENT_METHOD_NAME的常量值为"onEvent" String modifierString = methodName.substring(ON_EVENT_METHOD_NAME.length()); //依据后面的函数名来获取调用模式 ThreadMode threadMode; if (modifierString.length() == 0) { threadMode = ThreadMode.PostThread; } else if (modifierString.equals("MainThread")) { threadMode = ThreadMode.MainThread; } else if (modifierString.equals("BackgroundThread")) { threadMode = ThreadMode.BackgroundThread; } else if (modifierString.equals("Async")) { threadMode = ThreadMode.Async; } else { if (skipMethodVerificationForClasses.containsKey(clazz)) { continue; } else { throw new EventBusException("Illegal onEvent method, check for typos: " + method); } } }

接下来来看post是怎么实现的

public void post(Object event) {        PostingThreadState postingState = currentPostingThreadState.get();        List eventQueue = postingState.eventQueue;        eventQueue.add(event);        if (!postingState.isPosting) {            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;            }        }    }

叽里呱啦一大堆,好烦啊。。然后点点点 看到了这种方法

void invokeSubscriber(Subscription subscription, Object event) {        try {            subscription.subscriberMethod.method.invoke(subscription.subscriber, event);        } catch (InvocationTargetException e) {            handleSubscriberException(subscription, event, e.getCause());        } catch (IllegalAccessException e) {            throw new IllegalStateException("Unexpected exception", e);        }    }

当中非常重要一句就是

subscription.subscriberMethod.method.invoke(subscription.subscriber, event);

他实际上就是在调用我们订阅者的函数啦。这里返回来去调用我们注冊的订阅者的方法。也就是通知到啦~~

最后我们再来看看unregister 注销的方法

public synchronized void unregister(Object subscriber) {        List

>> subscribedTypes = typesBySubscriber.get(subscriber); if (subscribedTypes != null) { for (Class<?> eventType : subscribedTypes) { unubscribeByEventType(subscriber, eventType); } typesBySubscriber.remove(subscriber); } else { Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass()); } }

非常easy的。

仅仅是做了个remove操作。。

最后

呐。这里 因温特巴斯猜想 就结束了,基本上是依照预期来做的。

这里学习一个未知的东西顺序是这样

  1. 学会用
  2. 猜想他的原理
  3. 模仿
  4. 看源代码验证猜想
  5. 有不一样的地方,去学习理解

因为水平有限。有错误请及时评论指出。蟹蟹!

啊哈哈哈,感谢。 假设你喜欢我的文章,求评论。请点击关注我。我们一同进步。

本demo地址:

參考文章:

你可能感兴趣的文章
【随便扯扯】Standby到底翻译成备用还是待机?
查看>>
信息系统项目管理师软考辅导——3年真题透解与全真模拟
查看>>
一个引号导致1个小时网站打不开
查看>>
从无到有,WebService Apache Axis2初步实践
查看>>
SQL Server 2012笔记分享-58:数据库文件管理2
查看>>
将字符串"123456"转换成"1,2,3,4,5,6"
查看>>
Jquery imgPreview demos
查看>>
Windows Universal 应用 – Tip Calculator
查看>>
LeetCode之Min Stack 实现最小栈
查看>>
sql 一些题目
查看>>
[算法] 应用版本更新逻辑
查看>>
apache kafka源码分析-Producer分析---转载
查看>>
Eclipse 的快捷键以及文档注释、多行注释的快捷键
查看>>
GridView视图(BaseAdapter)
查看>>
[Everyday Mathematics]20150117
查看>>
过滤3个字节以上的utf-8字符
查看>>
kill me heal me的链接
查看>>
集团企业信息化参考一
查看>>
RedHat Linux 下安装MPlayer 编译源代码方式
查看>>
一个排序算法的解析
查看>>