android中用于解耦的架構有EventBus,Otto,Rx系列。
本章先來說說對EventBus的使用。
引用一個圖檔:

EventBus使用分為3步:
1.定義event事件,就是一個自定義的類,類的作用要能用來攜帶資料和區分事件類型。
public class MessageEvent {
public final String message;
public int eventType;
public MessageEvent(String message,int eventType) {
this.message = message;
this.eventType = eventType;
}
}
2.訂閱事件:
注冊和登出總線,
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
接收釋出結果
// This method will be called when a MessageEvent is posted (in the UI thread for Toast)
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}
3.釋出事件:
所有注冊了該事件的訂閱者都會收到該事件
EventBus.getDefault().post(new MessageEvent("Hello everyone!"));
事件接收後,可以選擇在哪個線程模型中使用:
1.ThreadMode: POSTING
2 ThreadMode: MAIN
3 ThreadMode: BACKGROUND
4 ThreadMode: ASYNC
@Subscribe(threadMode = ThreadMode.POSTING) // ThreadMode is optional here
public void onMessage(MessageEvent event) {
log(event.message);
}
與post處于同一線程,是預設的處理模型。
// Called in Android UI's main thread
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(MessageEvent event) {
textField.setText(event.message);
}
主線程中處理,更新Ui
// Called in the background thread
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessage(MessageEvent event){
saveToDisk(event.message);
}
如果釋出事件是在主線程,那麼這裡的執行就在子線程;如果釋出事件是在子線程,那麼這裡執行所在的線程與釋出所線上程處于同一個線程。
// Called in a separate thread
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessage(MessageEvent event){
backend.send(event.message);
}
另起一個線程來處理。
4.一個小例子:
運作截圖:
說明了在釋出事件處于UI和子線程情況下,使用不同的線程模型接收事件的結果;
釋出事件在主線程的情況:
釋出事件在子線程的情況:
具體代碼如下:
所有事件的基類:其他事件繼承該類;
<span style="font-size:14px;">public class BaseEvent {
private int eventType;
public BaseEvent(int eventType) {
super();
this.eventType = eventType;
}
public int getEventType() {
return eventType;
}
public void postEvent() {
EventBus.getDefault().post(this);
}
}</span>
所有的事件類型定義:用一個整形值來區分不同僚件
<span style="font-size:14px;">public interface EventType {
public static final int CONSTANT = 1;
public static final int EVENT_TYPE_SENDMSG = CONSTANT << 1;
}</span>
自定義的一個事件類型:
<span style="font-size:14px;">public class SendMsgEvent extends BaseEvent {
public SendMsgEvent(int eventType) {
super(eventType);
}
public String msg;
}</span>
MainActivity.java
<span style="font-size:14px;">public class MainActivity extends Activity {
private TextView tv_async;
private TextView tv_background;
private TextView tv_main;
private TextView tv_post;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// EventBus注冊,訂閱事件
EventBus.getDefault().register(this);
tv_async = (TextView) findViewById(R.id.tv_async);
tv_background = (TextView) findViewById(R.id.tv_background);
tv_main = (TextView) findViewById(R.id.tv_main);
tv_post = (TextView) findViewById(R.id.tv_post);
findViewById(R.id.bt_main).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 釋出事件
sendMsg();
}
});
findViewById(R.id.bt_sub).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 釋出事件
new Thread() {
public void run() {
sendMsg();
};
}.start();
}
});
}
// 處理訂閱的事件,android中常用這個,方法名任意隻要有注解就行
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage_Main(BaseEvent event) {
switch (event.getEventType()) {
case EventType.EVENT_TYPE_SENDMSG:
SendMsgEvent sendMsgEvent = (SendMsgEvent) event;
disText(tv_main,sendMsgEvent.msg);
break;
}
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessage_Async(BaseEvent event) {
switch (event.getEventType()) {
case EventType.EVENT_TYPE_SENDMSG:
SendMsgEvent sendMsgEvent = (SendMsgEvent) event;
disText(tv_async,sendMsgEvent.msg);
break;
}
}
@Subscribe(threadMode = ThreadMode.POSTING)
public void onMessage_Post(BaseEvent event) {
switch (event.getEventType()) {
case EventType.EVENT_TYPE_SENDMSG:
SendMsgEvent sendMsgEvent = (SendMsgEvent) event;
disText(tv_post,sendMsgEvent.msg);
break;
}
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessage_Background(BaseEvent event) {
switch (event.getEventType()) {
case EventType.EVENT_TYPE_SENDMSG:
SendMsgEvent sendMsgEvent = (SendMsgEvent) event;
disText(tv_background,sendMsgEvent.msg);
break;
}
}
private void disText(final TextView tv, final String msg) {
final String processThread = Thread.currentThread().getName();
tv.post(new Runnable() {
@Override
public void run() {
tv.setText(msg+"\n process event in "+processThread);
}
});
}
private void sendMsg() {
SendMsgEvent sendMsgEvent = new SendMsgEvent(
EventType.EVENT_TYPE_SENDMSG);
sendMsgEvent.msg = "post event in " + Thread.currentThread().getName();
sendMsgEvent.postEvent();
}
@Override
protected void onDestroy() {
super.onDestroy();
// EventBus登出,取消訂閱事件
EventBus.getDefault().unregister(this);
}
}</span>
activity_main.xml
<span style="font-size:14px;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="${relativePackage}.${activityClass}" >
<Button
android:id="@+id/bt_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="send in maintThread" />
<Button
android:id="@+id/bt_sub"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="send in subThread" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="result:\nmain\npost\nasync\nbackground" />
<TextView
android:id="@+id/tv_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="result" />
<TextView
android:id="@+id/tv_post"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="result" />
<TextView
android:id="@+id/tv_async"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="result" />
<TextView
android:id="@+id/tv_background"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="result" />
</LinearLayout></span>