自己動手,打造自己的事件總線工具類
你還在爲幾個界面間的數據傳遞煩惱嗎?你還在爲廣播的濫用蛋疼嗎?你還在爲開源庫的選擇糾結嗎?
那就自己動手寫個事件總線吧。雖然開源社區已經提供了很多開源框架,EventBus, 基於Rxjava的事件總線框架,都是很強大的,不僅減小了項目難度,還減少了很多代碼,但是奔着自己動手,豐衣足事的態度,還是我們自己動手寫一個工具類,不僅可以鞏固知識,還可以相互討論:
目錄如下:
- 定義觀察者
- 事件類
- 事件總線類定義
- 代碼測試
定義觀察者
第一步當然是定義我們的觀察者,當事件發生之後,來消費事件的對象 ,no B B ,show me code:
/**
* Author : yzx
* E-mail: [email protected]
* description : 觀察者,響應事件
*/
public interface Subscriber {
void onEventReceived(EventMessage eventMessage);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
代碼很簡單,需要觀察的對象實現此接口就ok了。
事件類
事件類 就是 上述接口 出現的EventMessage 類了:
public class EventMessage<T> {
//發送目標
private Class target;
//攜帶的數據
private T data;
// 類型,用於返回給同一個觀察者不同數據的判斷字段
private int type;
public EventMessage(Class target, T data, int type) {
this.target = target;
this.data = data;
this.type = type;
}
public Class getTarget() {
return target;
}
public void setTarget(Class target) {
this.target = target;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
- 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
這個類就是我們需要發送的事件類了,class 就是要發送的目標對象,data 是需要發送的數據,用泛型定義,可以攜帶任何類型,type的作用相當於Activity的requestCode(跳轉請求碼), 用於區分同一個接收目標不同業務的字段。
事件總線類定義
事件總線類: 發送事件,和分發事件的業務類。
public class EventLine {
private static final String TAG = "EventLine";
//觀察者 集合
private static ArrayList<Subscriber> subscribers = new ArrayList<>();
/**
* 發送事件
* */
public static void postEvent(EventMessage message) {
//如果 消息對象爲空,則發送給全體觀察者
if(message.getTarget() == null){
int size = subscribers.size();
for (int i = 0; i < size; i++) {
subscribers.get(i).onEventReceived(message);
}
}else{
//如果 消息對象爲特定對象,則發送給目標觀察者
int size = subscribers.size();
for (int i = 0; i < size; i++) {
if(subscribers.get(i).getClass() == message.getTarget()){
subscribers.get(i).onEventReceived(message);
}
}
}
}
/**
* 註冊觀察者
* */
public static void registerSubscriber(Subscriber subscriber) {
if (!subscribers.contains(subscriber)) {
subscribers.add(subscriber);
}
}
/**
* 註銷觀察者
* */
public static void unRegisterSubscriber(Subscriber subscriber) {
if (subscribers.contains(subscriber)) {
subscribers.remove(subscriber);
}
}
}
- 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
首先定義一個靜態集合類,用於註冊和註銷觀察者。
registerSubscriber(Subscriber subscriber): 用於註冊觀察者,在Actvity的onCreate()方法 或者 Fragment的 onCreateView()方法裏面註冊。
unRegisterSubscriber(Subscriber subscriber): 用於註銷觀察者,在Actvity的onDestory()方法 或者 Fragment的onViewCreated()方法裏面註銷。
需要注意的是:一定要註銷觀察者!一定要註銷觀察者!一定要註銷觀察者!因爲靜態集合的強引用,如果不主動註銷,會引起內存泄漏。
postEvent(EventMessage message): 發送事件,根據消息的target字段決定發送給什麼對象,根據type處理不同的義務。
Activity基類
如果你已經有一個自己的Activity基類或者Fragment基類,可以直接在相應方法裏面調用訂閱和註銷方法
public abstract class BaseEventActivity extends BaseActivity implements Subscriber {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EventLine.registerSubscriber(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
EventLine.unRegisterSubscriber(this);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
而後,在需要的界面實現Subscriber接口,關於控件綁定的代碼就不貼了:
public class TestAct1 extends BaseEventActivity {
@OnClick({R.id.activity_test_act1_tv1, R.id.activity_test_act1_tv2})
public void onClick(View view) {
switch (view.getId()) {
//跳轉至第二個界面
startActivity(new Intent(TestAct1.this, TestAct2.class));
break;
case R.id.activity_test_act1_tv2:
break;
}
}
@Override
public void onEventReceived(EventMessage eventMessage) {
//不同的業務不同的處理
if (eventMessage.getType() == 1) {
activityTestAct1Tv2.setText((String) eventMessage.getData());
} else if (eventMessage.getType() == 0) {
finish();
} else {
}
}
}
- 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
每個界面只有兩個TextView, 一個用於跳轉,另一個用於顯示 接收到的數據
public class TestAct2 extends BaseEventActivity {
@OnClick({R.id.activity_test_act2_tv1, R.id.activity_test_tv2})
public void onClick(View view) {
switch (view.getId()) {
case R.id.activity_test_act2_tv1:
startActivity(new Intent(TestAct2.this, TestAct3.class));
break;
case R.id.activity_test_tv2:
break;
}
}
@Override
public void onEventReceived(EventMessage eventMessage) {
if(eventMessage.getType() == 1){
activityTestAct2Tv2.setText((String)eventMessage.getData());
} else if (eventMessage.getType() == 0) {
finish();
} else {
}
}
}
public class TestAct3 extends BaseEventActivity {
@OnClick({R.id.activity_test_act3_tv1, R.id.activity_test_act3_tv2})
public void onClick(View view) {
switch (view.getId()) {
case R.id.activity_test_act3_tv1:
startActivity(new Intent(TestAct3.this, TestAct4.class));
break;
case R.id.activity_test_act3_tv2:
break;
}
}
@Override
public void onEventReceived(EventMessage eventMessage) {
if(eventMessage.getType() == 1){
activityTestAct3Tv2.setText((String)eventMessage.getData());
} else if (eventMessage.getType() == 0) {
finish();
} else {
}
}
}
- 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
- 56
第四個界面 代碼如下,一個用於顯示數據和發送關閉事件,另一個用於發送各個界面特定消息
public class TestAct4 extends BaseEventActivity {
@OnClick({R.id.activity_test_act4_tv1, R.id.activity_test_act4_tv2, R.id.activity_test_act4_tv3})
public void onClick(View view) {
switch (view.getId()) {
case R.id.activity_test_act4_tv2:
EventLine.postEvent(new EventMessage<>(TestAct1.class, "發給界面1的消息", 1));
EventLine.postEvent(new EventMessage<>(TestAct2.class, "發給界面2的消息", 1));
EventLine.postEvent(new EventMessage<>(TestAct3.class, "發給界面3的消息", 1));
EventLine.postEvent(new EventMessage<>(TestAct4.class, "發給界面4的消息", 1));
break;
case R.id.activity_test_act4_tv3:
EventLine.postEvent(new EventMessage<>(null, "全體關閉", 0));
break;
}
}
@Override
public void onEventReceived(EventMessage eventMessage) {
if(eventMessage.getType() == 1){
activityTestAct4Tv2.setText((String)eventMessage.getData());
} else if (eventMessage.getType() == 0) {
finish();
} else {
}
}
}
- 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
代碼全部展示完畢,下面看看效果:
1:發送事件前
2 : 發送事件後 (按照Activity回退棧的順序展示圖片,每按一次回退鍵,截一次圖 = =!)
可以看到:第四個界面分別向 1、2、3、4界面分別發送一個字符串,在接收到相應字符串之後,各個觀察者都展示在屏幕中央。
在點擊關閉事件 按鈕後:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
當然是全部銷燬關閉了唄。