实例讲解EventBus的使用

作者: 手指乐 | 来源:发表于2019-08-20 14:14 被阅读6次

    EventBus介绍

    EventBus用于在任意类之间通讯(包括但不限于Activity,Fragment等),它基于发布/订阅机制,只要在任意一个类中订阅了消息,就可以接受到任意一个地方发布的该消息。
    下面通过一个实例来讲解EventBus的使用:



    点击左侧的Fragment发布消息,右侧的Fragment订阅消息,通过日志观察消息的发布和订阅及所在的线程

    1. 引入EventBus
      github地址:https://github.com/greenrobot/EventBus
      gradle配置
      implementation 'org.greenrobot:eventbus:3.1.1'
    2. 定义消息类
      消息类不一定是实体类,可以是任意的类
    /**
     *
     * 用于消息(事件)传输的实体类
     *
     * Created by zhouyi on 16/7/18.
     */
    public class MyEvent1 {
        private String mstrMsg;
    
    
        public MyEvent1(String strMsg){
            mstrMsg = strMsg;
        }
    
        public String getMsg(){
            return mstrMsg;
        }
    
    }
    
    1. 左侧Fragment使用不同的线程发布消息:
      使用post方法发布消息即可
    public class LeftFragment extends ListFragment {
    
        @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            String[] strs = new String[]{"主线程消息1", "子线程消息1", "主线程消息2"};
            setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, strs));
        }
    
        @Override
        public void onListItemClick(ListView l, View v, int position, long id) {
    
            switch (position) {
                case 0:
                    String strMsg = "LeftFragment中主线程发送消息1";
                    Log.d("qf", "----主线程发送消息,线程名:"
                            + Thread.currentThread().getName()
                            + ",线程id"
                            + Thread.currentThread().getId()
                            + ",消息内容:"
                            + strMsg
                            + "-----");
                    EventBus.getDefault().post(new MyEvent1(strMsg));
                    break;
                case 1:
                    new Thread(){
                        @Override
                        public void run() {
                            String strMsg = "LeftFragment中子线程发送消息1";
                            Log.d("qf", "----子线程发送消息,线程名:"
                                    + Thread.currentThread().getName()
                                    + ",线程id"
                                    + Thread.currentThread().getId()
                                    + ",消息内容:"
                                    + strMsg
                                    + "-----");
                            EventBus.getDefault().post(new MyEvent1(strMsg));
                        }
                    }.start();
    
                    break;
                case 2:
    
                    break;
            }
        }
    
    }
    
    1. 右侧的Fragment订阅消息
      首先通过register方法注册
      然后使用Subscribe注解来订阅消息,Subscribe注解中可以指定消息响应的线程和发布线程的关系
      最后使用unregister解除注册
      发布和订阅通过实体类关联,订阅的实体类跟发布一样,就可以收到消息
    public class RightFragment extends Fragment {
    
        private TextView mtvMsg;
        
    
        @Override
        public void onDestroy() {
            super.onDestroy();
    
            EventBus.getDefault().unregister(this);
        }
    
    
        /**
         * 默认情况下,如果消息是主线程发送的,那么消息的响应者(接收者)
         * 就在主线程运行
         * 如果消息是子线程发送的,那么消息的响应者(接收者)
         * 就在子线程运行
         * @param event1
         */
        @Subscribe
        public void onEvent(MyEvent1 event1){
            String strMsg = event1.getMsg();//得到消息里面传输过来的内容
            Log.d("qf","onEvent接收到消息,线程名:"
                    +Thread.currentThread().getName()
                    +",线程id"
                    +Thread.currentThread().getId()
                    +",消息内容:"
                    +strMsg
                    );
            //mtvMsg.setText(strMsg);
        }
    
        /**
         * 不管发送方是在哪个线程发送过来的消息,接收方都在主线程里进行处理
         */
        @Subscribe(threadMode = ThreadMode.MAIN)
        public void onEventMain(MyEvent1 event1){
            String strMsg = event1.getMsg();//得到消息里面传输过来的内容
            Log.d("qf","onEventMain接收到消息,线程名:"
                    +Thread.currentThread().getName()
                    +",线程id"
                    +Thread.currentThread().getId()
                    +",消息内容:"
                    +strMsg
            );
            mtvMsg.setText(strMsg);
        }
    
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            EventBus.getDefault().register(this);
    
            View view = inflater.inflate(R.layout.fragment_right, null);
            mtvMsg = (TextView) view.findViewById(R.id.tv);
            return view;
        }
    }
    
    1. 点击左侧第一个按钮,观察日志:
    ----主线程发送消息,线程名:main,线程id1,消息内容:LeftFragment中主线程发送消息1-----
    onEvent接收到消息,线程名:main,线程id1,消息内容:LeftFragment中主线程发送消息1
    onEventMain接收到消息,线程名:main,线程id1,消息内容:LeftFragment中主线程发送消息1
    

    此时消息从主线程发出,订阅者都从主线程响应

    1. 点击左侧第二个按钮,观察日志:
    ----子线程发送消息,线程名:Thread-145,线程id145,消息内容:LeftFragment中子线程发送消息1-----
    onEvent接收到消息,线程名:Thread-145,线程id145,消息内容:LeftFragment中子线程发送消息1
    onEventMain接收到消息,线程名:main,线程id1,消息内容:LeftFragment中子线程发送消息1
    

    此时消息从子线程发出,订阅消息的两个方法,第一个是默认方式,订阅线程跟发布线程一致
    第二个方法在注解中使用threadMode = ThreadMode.MAIN,不管发布者在哪个线程,订阅者都在主线程响应

    相关文章

      网友评论

        本文标题:实例讲解EventBus的使用

        本文链接:https://www.haomeiwen.com/subject/acqpsctx.html