你还在为几个界面间的数据传递烦恼吗?你还在为广播的滥用蛋疼吗?你还在为开源库的选择纠结吗?
那就自己动手写个事件总线吧。虽然开源社区已经提供了很多开源框架,EventBus, 基于Rxjava的事件总线框架,都是很强大的,不仅减小了项目难度,还减少了很多代码,但是奔着自己动手,丰衣足事的态度,还是我们自己动手写一个工具类,不仅可以巩固知识,还可以相互讨论:
目录如下:
第一步当然是定义我们的观察者,当事件发生之后,来消费事件的对象 ,no B B ,show me code:
/**
* Author : yzx
* E-mail: [email protected]
* description : 观察者,响应事件
*/
public interface Subscriber {
void onEventReceived(EventMessage eventMessage);
}
代码很简单,需要观察的对象实现此接口就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;
}
}
这个类就是我们需要发送的事件类了,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);
}
}
}
首先定义一个静态集合类,用于注册和注销观察者。
registerSubscriber(Subscriber subscriber): 用于注册观察者,在Actvity的onCreate()方法 或者 Fragment的 onCreateView()方法里面注册。
unRegisterSubscriber(Subscriber subscriber): 用于注销观察者,在Actvity的onDestory()方法 或者 Fragment的onViewCreated()方法里面注销。
需要注意的是:一定要注销观察者!一定要注销观察者!一定要注销观察者!因为静态集合的强引用,如果不主动注销,会引起内存泄漏。
postEvent(EventMessage message): 发送事件,根据消息的target字段决定发送给什么对象,根据type处理不同的义务。
如果你已经有一个自己的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);
}
}
而后,在需要的界面实现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 {
}
}
}
每个界面只有两个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 {
}
}
}
第四个界面 代码如下,一个用于显示数据和发送关闭事件,另一个用于发送各个界面特定消息
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 : 发送事件后 (按照Activity回退栈的顺序展示图片,每按一次回退键,截一次图 = =!)
可以看到:第四个界面分别向 1、2、3、4界面分别发送一个字符串,在接收到相应字符串之后,各个观察者都展示在屏幕中央。
在点击关闭事件 按钮后:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
当然是全部销毁关闭了呗。