自己动手,打造自己的事件总线

自己动手,打造自己的事件总线工具类

你还在为几个界面间的数据传递烦恼吗?你还在为广播的滥用蛋疼吗?你还在为开源库的选择纠结吗?

那就自己动手写个事件总线吧。虽然开源社区已经提供了很多开源框架,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 {
    //发送目标
    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 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:发送事件前

自己动手,打造自己的事件总线_第1张图片

自己动手,打造自己的事件总线_第2张图片

自己动手,打造自己的事件总线_第3张图片

自己动手,打造自己的事件总线_第4张图片

2 : 发送事件后 (按照Activity回退栈的顺序展示图片,每按一次回退键,截一次图 = =!)

自己动手,打造自己的事件总线_第5张图片

自己动手,打造自己的事件总线_第6张图片

自己动手,打造自己的事件总线_第7张图片

自己动手,打造自己的事件总线_第8张图片

可以看到:第四个界面分别向 1、2、3、4界面分别发送一个字符串,在接收到相应字符串之后,各个观察者都展示在屏幕中央。

在点击关闭事件 按钮后:

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

自己动手,打造自己的事件总线_第9张图片

当然是全部销毁关闭了呗。

你可能感兴趣的:(自己动手,打造自己的事件总线)