天天看點

android中EventBus總線架構的使用

android中用于解耦的架構有EventBus,Otto,Rx系列。

本章先來說說對EventBus的使用。

引用一個圖檔:

android中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和子線程情況下,使用不同的線程模型接收事件的結果;

釋出事件在主線程的情況:

android中EventBus總線架構的使用

釋出事件在子線程的情況:

android中EventBus總線架構的使用

具體代碼如下:

所有事件的基類:其他事件繼承該類;

<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>