自己動手,打造自己的事件總線

自己動手,打造自己的事件總線工具類

你還在爲幾個界面間的數據傳遞煩惱嗎?你還在爲廣播的濫用蛋疼嗎?你還在爲開源庫的選擇糾結嗎?

那就自己動手寫個事件總線吧。雖然開源社區已經提供了很多開源框架,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:發送事件前

TestAct1

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

2 : 發送事件後 (按照Activity回退棧的順序展示圖片,每按一次回退鍵,截一次圖 = =!)

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

可以看到:第四個界面分別向 1、2、3、4界面分別發送一個字符串,在接收到相應字符串之後,各個觀察者都展示在屏幕中央。

在點擊關閉事件 按鈕後:

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

這裏寫圖片描述

當然是全部銷燬關閉了唄。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章