#####常用事件消息传递

  • 一个实现了监听器接口的类,必须把它自身注册到它想要监听的类中去
  • 使用广播,内部的实现都需要IPC,从传递效率上来讲,可能并不太适合上层的组件间通信
  • Activity间的消息传递便是通过startActivityForResult和onActivityResult,会产生较多的状态和逻辑判断,而且intent或Bundle传值还得检测类型,容易发生错误

#####集成

1
compile 'org.greenrobot:eventbus:3.1.1'

EventBus是一款针对Anddoid优化的发布/订阅事件总线。主要是替代intent,Handler,
BroadCast在Fragment,activity,service线程之间传递消息。
优点:开销小,代码更优雅,以及将发送者和节后这解耦

#####基本用法

  • 注册
    1
    2
    EventBus.getDefault.register(this);
    EventBus.getDefault.register(this,methodName,Event.class);
  • 取消注册
    1
    EventBus.getDefault.unregister(this);
  • 订阅处理数据
    1
    2
    3
    onEventMainThread onEvent
    onEventPostThread onEventAsync
    onEventBackgroundThread
  • 发布数据
    1
    EventBus.getDefault().post(new Event(msg));

#####简单的demo

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public class MainActivity extends AppCompatActivity {
//第一个界面
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);//注册
findViewById(R.id.bn_main).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(MainActivity.this,SecondActivity.class));
}
});
}
@Subscribe(threadMode = ThreadMode.MAIN)//需要加上注解
public void onEventMainThred(MyEvent event){
Log.e("tyl","masg="+event.getEvent());

}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);//注销
}
}
//第二个界面
public class SecondActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.bn_main).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MyEvent myEvent = new MyEvent();
myEvent.setEvent("hello");
EventBus.getDefault().post(myEvent);
finish();
}
});
}
}
//消息源
public class MyEvent {
private String event;

public String getEvent() {
return event;
}

public void setEvent(String event) {
this.event = event;
}
}

#####ThreadMode分类
在EventBus中,您可以使用四个ThreadModes中的一个来定义将调用事件处理方法的线程。

  • ThreadMode.POSTING
    订阅者将在发布事件的同一线程中调用。这是默认值。事件传递是同步完成的,一旦发布完成,所有订阅者都将被调用。此ThreadMode意味着开销最小,因为它完全避免了线程切换。因此,这是已知完成的简单任务的推荐模式,是一个非常短的时间而不需要主线程。使用此模式的事件处理程序应该快速返回以避免阻止发布线程,这可能是主线程。
    1
    2
    3
    4
    5
    6
    //在同一个线程中调用(默认)
    // ThreadMode在这里是可选的
    @Subscribe(threadMode = ThreadMode.POSTING)
    public void onMessageEvent(MessageEvent event) {
    textView.setText(event.message);
    }
  • ThreadMode.MAIN
    订阅者将在Android的主线程(有时称为UI线程)中调用。如果发布线程是主线程,则将直接调用事件处理程序方法(与ThreadMode.POSTING所描述的同步)。使用此模式的事件处理程序必须快速返回以避免阻塞主线程。
    1
    2
    3
    4
    5
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(MessageEvent event) {
    Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
    textView.setText(event.message);
    }
  • ThreadMode.MAIN_ORDERED
    订阅者将在Android的主线程中调用。该事件总是排队等待以后交付给订阅者,因此对post的调用将立即返回。这为事件处理提供了更严格且更一致的顺序(因此名称为MAIN_ORDERED)。例如,如果您在具有MAIN线程模式的事件处理程序中发布另一个事件,则第二个事件处理程序将在第一个事件处理程序之前完成(因为它是同步调用的 - 将其与方法调用进行比较)。使用MAIN_ORDERED,第一个事件处理程序将完成,然后第二个事件处理程序将在稍后的时间点调用(一旦主线程具有容量),使用此模式的事件处理程序必须快速返回以避免阻塞主线程。
    1
    2
    3
    4
    5
    6
    //在Android UI主线程中调用
    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    public void onMessageEvent(MessageEvent event) {
    Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
    textView.setText(event.message);
    }
  • ThreadMode.BACKGROUND
    订阅者将在后台线程中调用。如果发布线程不是主线程,则将在发布线程中直接调用事件处理程序方法。如果发布线程是主线程,则EventBus使用单个后台线程,该线程将按顺序传递其所有事件。使用此模式的事件处理程序应尝试快速返回以避免阻塞后台线程。
    1
    2
    3
    4
    5
    //在后台线程中调用
    @Subscribe(threadMode = ThreadMode.BACKGROUND)
    public void onMessage(MessageEvent event){
    saveToDisk(event.message);
    }
  • ThreadMode.ASYNC
    事件处理程序方法在单独的线程中调用。这始终独立于发布线程和主线程。发布事件永远不会等待使用此模式的事件处理程序方法。如果事件处理程序的执行可能需要一些时间,例如用于网络访问,则应使用此模式。避免同时触发大量长时间运行的异步处理程序方法来限制并发线程数。EventBus使用线程池从已完成的异步事件处理程序通知中有效地重用线程。
    1
    2
    3
    4
    5
    //在一个单线程中调用
    @Subscribe(threadMode = ThreadMode.ASYNC)
    public void onMessage(MessageEvent event){
    backend.send(event.message);
    }

#####总结
我们根据EventBus中的不同ThreadMode的方式来进行对我们项目的使用,在什么情况中使用哪种线程将是我们所需要考虑的。
根据Android 中的线程不同,来使用不同的EventBus的不同线程。