EventBus sticky事件

相信会有人遇到过这种需求:启动应用进入到首页后,会有一个或若干个网络请求,请求网络获取数据后要更新View。如果此时网络访问有延时,这个时候进入到首页后,View更新便会造成画面更新的闪动,这样用户体验不太好。所以我们一般会引入一个 SplashActivity(启动页)来解决这个问题,将数据初始化操作先放到这里。

那么,现在问题来了:在 SplashActivity 执行一个后台请求网络获取数据的操作,又怎么将数据发送到首页 MainActivity 呢?

  • 1.用广播 ?假如 MainActivity 还没有 onCreate ,SplashActivity 就发送数据到 MainActivity,广播还能收到消息么 ?

  • 2.用Sticky Broadcast ?嗯,可以的。Sticky Broadcast可以在广播发送结束后保存刚刚发送的广播(Intent),这样当接收者注册完Receiver后就可以接收到刚才已经发布的广播。

    OK,问题已经差不多解决了。但是,用广播会不会未免太重了?

在这里,我无情安利一个非常好用的框架EventBus。它可以很方便的发送一种 sticky 事件,就可以实现粘性广播的效果。在 SplashActivity 发送sticky 事件时,EventBus 会先存储这个 sticky 事件,当接收事件端 MainActivity 加载完成的时候,便会响应这个 sticky 事件。

二、为何要安利EventBus:

在使用EventBus时,完全不需要再配置其他东西,例如在Application配置什么。而且发送事件的时候完全不用管接收事件端是什么,也不需要绑定接收事件端。高度解耦,而且在某些场合非常便利:比如activity各种跳转返回的处理、activity 和 多级嵌套 fragment 之间的数据传递。如此优秀的框架便成为了我安利的理由。

三、EventBus 的简单介绍:

1.添加eventbus依赖

compile ‘de.greenrobot:eventbus:2.4.0’

2.EventBus 的使用非常简单,一般只需要用到这3个方法。

  • EventBus.getDefault().post(object); // 发布事件
  • EventBus.getDefault().register(this); // 订阅事件
  • EventBus.getDefault().unregister(this); // 取消订阅

发送端只需要直接发送事件。
接收事件端:
1、必须订阅事件、取消订阅
2、提供处理事件的方法(eventbus3.0后需要在方法名前加注解)

在这里我简单画一个图来介绍使用方法吧:

实际上,EventBus是基于事件总线型的设计,将事件都统一发送到了EventBus总线处,然后再由EventBus分发到事件接收处。

四、EventBus 实践 【发送sticky事件】:

在 SplashActivity 中隔3秒后启动 MainActivity。在这里模拟一个线程消耗1秒钟获取到数据后发送sticky事件出去。【假如不用sticky事件,则事件接收端由于还没有初始化,接收端将永远收不到消息。】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class SplashActivity extends AppCompatActivity {

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

new Handler().postDelayed(new Runnable() {
@Override
public void run() {
startActivity(new Intent(SplashActivity.this,MainActivity.class));
}
},3000);



new Thread(new Runnable() {

@Override
public void run() {
SystemClock.sleep(1000);
EventBus.getDefault().postSticky(new String("hello"));
}

}).start();
}
}

在 MainActivity 中接收事件。在这里需要注意的是:EventBus.getDefault().registerSticky(this);一定要放在控件初始化之后。因为,这句话执行的时候,就会去调用onEventMainThread方法,如果在控件初始化之前,则会报控件TextView空指针。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class MainActivity extends AppCompatActivity {

private TextView mTextView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.text);

EventBus.getDefault().registerSticky(this);
}

@Override
protected void onStart() {
super.onStart();

}

@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}

public void onEventMainThread(String event) {
mTextView.setText(event);
}
}

demo运行效果图:

Android Eventbus