EventBus3.0实现发送事件后再注册依然能获取到事件的效果

时间过得很快,转眼迎来了清明小长假,在小长假到来前期搞定了一个问题,心里还是很高兴的,这里分享给大家,希望大家遇到相同问题时能有有所帮助。

先说一下我的需求吧,在手头的项目里有这么一个需求,就是一个activity,它有三个fragment,activity要通过网络从服务端获取数据,然后分发给三个fragment展示。

最初,我是想用broadcastReceiver实现的,但是写了一堆代码以后发现不是想象的那么简单。当activity获取到数据后发送广播,此时FragmentA和FragmentB已经初始化完毕,当然也完成了BroadcastReceiver的注册,这两个是可以接受到activity传递过来的数据的,但是FragmentC就尴尬了,在activity发送广播的时候它还没有初始化,也就没有注册广播接收器,自然也就没有数据展示了。这个问题让我很是头大了一会儿,后来考虑的用一下EventBus试试,结果一试还真成了,哈哈哈哈,先让我笑几声,然后在这里记录一下EventBus的使用吧。

首先,添加依赖库:

Androidstudio的gradle配置如下:

compile 'org.greenrobot:eventbus:3.0.0'
然后,定义一个MessageEvent类:
public class MessageEvent {
    private String message;

    public MessageEvent(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
第三,在三个Fragment中注册、订阅事件:
public class FragmentA extends Fragment {
    private static final String TAG = "FragmentA";
    private TextView tvAAA;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View view=inflater.inflate(R.layout.fragment_aa,container,false);
        tvAAA=view.findViewById(R.id.text_a);

        Log.d(TAG, "onCreateView: ");
        //注册
        EventBus.getDefault().register(this);

        return view;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.d(TAG, "onDestroyView: ");
        //注销
        EventBus.getDefault().unregister(this);
    }
}
第四,事件订阅者处理事件。这里多说几句,如果是普通的事件,无法实现刚开始说的事件先发送,后注册获取的效果,所以这里使用的是EventBus 的 黏性事件,这个可以非常好的达到我们的要求。

    //事件订阅者处理事件,必须有此方法
    //这里我们的ThreadMode设置为MAIN,事件的处理会在UI线程中执行,用TextView来展示收到的事件消息
    //注意,这里的注解里必须有sticky,并将值设置为true,表示与事件绑定,可以在事件已经发送但是还没有注册的情况下,一旦注册,就可以接受到数据
    @Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
    public void onResult(MessageEvent messageEvent){
        tvAAA.setText(messageEvent.getMessage());
    }
最后,发送黏性事件:
private void sendMsg() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {

                            EventBus.getDefault().postSticky(new MessageEvent("here is activity"));

                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

简单的几行代码就实现了我们的要求是不是感觉so easy,不过效果虽然实现了,但是我们真正懂得了EventBus了吗,未必!下面大概了解一下EventBus:

EventBus的三要素

EventBus有三个主要的元素需要我们先了解一下:

  • Event:事件,可以是任意类型的对象。
  • Subscriber:事件订阅者,在EventBus3.0之前消息处理的方法只能限定于onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,他们分别代表四种线程模型。而在EventBus3.0之后,事件处理的方法可以随便取名,但是需要添加一个注解@Subscribe,并且要指定线程模型(默认为POSTING),四种线程模型下面会讲到。
  • Publisher:事件发布者,可以在任意线程任意位置发送事件,直接调用EventBus的post(Object)方法。可以自己实例化EventBus对象,但一般使用EventBus.getDefault()就好了,根据post函数参数的类型,会自动调用订阅相应类型事件的函数。

EventBus的四种ThreadMode(线程模型)

EventBus3.0有以下四种ThreadMode:

  • POSTING(默认):如果使用事件处理函数指定了线程模型为POSTING,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。在线程模型为POSTING的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起ANR。
  • MAIN: 
    事件的处理会在UI线程中执行。事件处理时间不能太长,长了会ANR的。
  • BACKGROUND:如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。
  • ASYNC:无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行,同样,此事件处理函数中禁止进行UI更新操作。
好了,就记录这么多吧,学海无涯!!!

你可能感兴趣的:(EventBus3.0实现发送事件后再注册依然能获取到事件的效果)