Android开发Android开发经验谈Android技术知识

实例讲解EventBus的使用

2019-08-20  本文已影响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,不管发布者在哪个线程,订阅者都在主线程响应

上一篇下一篇

猜你喜欢

热点阅读