相信会有人遇到过这种需求:启动应用进入到首页后,会有一个或若干个网络请求,请求网络获取数据后要更新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时,完全不需要再配置其他东西,例如在Application配置什么。而且发送事件的时候完全不用管接收事件端是什么,也不需要绑定接收事件端。高度解耦,而且在某些场合非常便利:比如activity各种跳转返回的处理、activity 和 多级嵌套 fragment 之间的数据传递。如此优秀的框架便成为了我安利的理由。
1.添加eventbus依赖
compile ‘de.greenrobot:eventbus:2.4.0’
2.EventBus 的使用非常简单,一般只需要用到这3个方法。
发送端只需要直接发送事件。
接收事件端:
1、必须订阅事件、取消订阅
2、提供处理事件的方法(eventbus3.0后需要在方法名前加注解)
在这里我简单画一个图来介绍使用方法吧:
实际上,EventBus是基于事件总线型的设计,将事件都统一发送到了EventBus总线处,然后再由EventBus分发到事件接收处。
在 SplashActivity 中隔3秒后启动 MainActivity。在这里模拟一个线程消耗1秒钟获取到数据后发送sticky事件出去。【假如不用sticky事件,则事件接收端由于还没有初始化,接收端将永远收不到消息。】
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空指针。
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运行效果图: