• 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);
                }
            }
        }
    
  • 相关阅读:
    SharePoint 2013中的Index Partition的一个小问题
    SharePoint 2013中, 默认Index文件的位置
    Visual Studio Test Project的一个小问题
    HyperV最佳实践
    测试环境中的一个HyperV的选项设置
    什么是SharePoint 2013中的Shredded Storage?
    SharePoint的数据库性能需要注意的一点
    记录HyperV中挪动虚拟机的一次实践
    SharePoint 2013上一台机器可以有多个Crawl Component么?
    SharePoint Client Object Model的一个小例子
  • 原文地址:https://www.cnblogs.com/baorantHome/p/15889398.html
Copyright © 2020-2023  润新知