eventBus使用和及源码初步梳理

eventBus使用和及源码初步梳理

一、eventbus简介

EventBus是一种用于Android的事件发布-订阅总线,由GreenRobot开发。它简化了应用程序内各个组件、线程之间进行通信的复杂度,尤其是碎片之间进行通信的问题,可以避免由于使用广播通信而带来的诸多不便。

1.1 三个重要角色

Event:事件对象,它可以是任意类型,EventBus会根据事件类型进行全局的通知。
Subscriber:事件订阅者,在EventBus 3.0之前我们必须定义以onEvent开头的那几个方法,分别是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe,并且指定线程模型,默认是POSTING。
Publisher:事件的发布者,可以在任意线程里发布事件。一般情况下,使用EventBus.getDefault()就可以得到一个EventBus对象,然后再调用post(Object)方法即可。

1.2 四种线程模型

EventBus3.0有四种线程模型,分别是:
POSTING:默认,表示事件处理函数的线程跟发布事件的线程在同一个线程。
MAIN:表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作。
BACKGROUND:表示事件处理函数的线程在后台线程,因此不能进行UI操作。
ASYNC:表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作。

二、EventBus 使用

2.1 先要引入如下依赖:

implementation 'org.greenrobot:eventbus:3.1.1'

2.2 定义注册事件类型

public class MessageWrap {
    public final String message;
    public static MessageWrap getInstance(String message) {
        return new MessageWrap(message);
    }
    private MessageWrap(String message) {
        this.message = message;
    }
}

2.3 注册事件监听

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    Button btn;
    TextView tv;

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

        btn = findViewById(R.id.btnRegister);
        tv = findViewById(R.id.tv);
        **EventBus.getDefault().register(this);**

        btn.setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, MainActivity2.class);
            startActivity(intent);
        });
    }
    
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onGetMessage(MessageWrap message) {
        Log.d(TAG, "onGetMessage: " + message);
        tv.setText(message.message);
    }
    .......

2.4 发布监听消息

public class MainActivity2 extends AppCompatActivity {
    TextView tv2;
    Button btn2;

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

        tv2 = findViewById(R.id.tv2);
        btn2 = findViewById(R.id.btn2);

        btn2.setOnClickListener(v -> {
            **EventBus.getDefault().post(MessageWrap.getInstance("Main2"));**
        });
    }
}

2.5 查看监听效果


三、黏性事件
一般使用的时候,都会和上面的demo类似的执行顺序,订阅者先订阅事件监听,被订阅者再发送消息,然后订阅者接受事件监听。如果想要被订阅者发送事件消息后,订阅者再订阅仍能收到消息,就需要用到eventBus的黏性事件。代码修改点如下:
订阅者订阅黏性事件:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    Button btn;
    Button btn1;
    TextView tv;

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

        btn = findViewById(R.id.btnRegister);
        tv = findViewById(R.id.tv);
        btn1 = findViewById(R.id.btn1);
//        EventBus.getDefault().register(this);

        btn.setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, MainActivity2.class);
            startActivity(intent);
        });
        btn1.setOnClickListener(v -> {
            // 点击注册按钮注册黏性事件
            EventBus.getDefault().register(this);
        });
    }

    // 订阅黏性事件
    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void onGetMessage(MessageWrap message) {
        Log.d(TAG, "onGetMessage: " + message);
        tv.setText(message.message);
    }

被订阅者发布黏性事件:

public class MainActivity2 extends AppCompatActivity {
    TextView tv2;
    Button btn2;

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

        tv2 = findViewById(R.id.tv2);
        btn2 = findViewById(R.id.btn2);

        btn2.setOnClickListener(v -> {
//            EventBus.getDefault().post(MessageWrap.getInstance("Main2"));
            // 发布黏性事件
            EventBus.getDefault().postSticky(MessageWrap.getInstance("Main2"));
        });
    }
}

log日志:

2.6 源码查看

2.6.1 发送黏性事件后

org.greenrobot.eventbus.EventBus#postSticky

    public void postSticky(Object event) {
        synchronized (stickyEvents) {
            // stickyEvents集合存下黏性事件
            stickyEvents.put(event.getClass(), event);
        }
        // Should be posted after it is putted, in case the subscriber wants to remove immediately
        post(event);
    }

org.greenrobot.eventbus.EventBus#post

    public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get();
        List<Object> **eventQueue** = postingState.eventQueue;
        eventQueue.add(event);

        if (!postingState.isPosting) {
            postingState.isMainThread = isMainThread();
            postingState.isPosting = true;
            if (postingState.canceled) {
                throw new EventBusException("Internal error. Abort state was not reset");
            }
            try {
                // eventQueue不为空,会发送事件
                while (!eventQueue.isEmpty()) {
                    postSingleEvent(eventQueue.remove(0), postingState);
                }
            } finally {
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }

2.6.2 订阅者订阅黏性事件

org.greenrobot.eventbus.EventBus#register

    public void register(Object subscriber) {
        Class<?> subscriberClass = subscriber.getClass();
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

org.greenrobot.eventbus.EventBus#subscribe

    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        Class<?> eventType = subscriberMethod.eventType;
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        ......
        if (subscriberMethod.sticky) {
            if (eventInheritance) {
            ....
            // 获取stickyEvents集合中的黏性事件数据,对照发送时存取数据
                Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
                for (Map.Entry<Class<?>, Object> entry : entries) {
                    Class<?> candidateEventType = entry.getKey();
                    if (eventType.isAssignableFrom(candidateEventType)) {
                        Object stickyEvent = entry.getValue();
                        checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                    }
                }
            } else {
                Object stickyEvent = stickyEvents.get(eventType);
                checkPostStickyEventToSubscription(newSubscription, stickyEvent);
            }
        }
    }

posted on 2022-02-13 15:07  baorant  阅读(71)  评论(0编辑  收藏  举报

导航