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>