本篇是 SAHADEV 是第二篇投稿,不同于之前的译文,今天他亲自编写了示例来阐述责任链模式。
SAHADEV 的博客地址:http://blog.csdn.net/sahadev_
责任链其实在Android中出现的频率还蛮高的,事件传递就是一种责任链机制。接下来我为大家介绍在开发应用时责任链的用处:
触摸事件的应用。
响应事件的应用。
何为责任链?责任链说白了就是一个事件传递的链条,一般这个链条上有很多个事件消费者,每个事件消费者都有机会接收并消费事件:
第一个对象如果可以处理,则处理后返回,如果不能处理,则将事件传递下一个对象处理,以此推类。
那么它究竟在Android中有什么用呢,大伙可能知道,Android我们最为熟悉的就是Touch事件传递了,这就是一个典型的责任链模式。为了介绍的更直观一点,我简单画了一个界面:
上面的情况Android中有时候会遇到。有时界面上会弹出好几个这种临时显示的窗体或者控件,它们只是为了显示一下,然后需要用户关闭,常常我们希望可以按下返回键将它们关闭。
如果不使用责任链的话代码就会写成这个样子:
if(A.isShow()){
A.dismiss();
}else if(B.isShow()){
B.dismiss();
}else if(C.isShow()){
C.dismiss();
}else if(D.isShow()){
D.dismiss();
}
如果只有一两个,这么写也不会有什么错。但如果情况复杂了的话,这么写,设计上可就不妙了。所以这种情况极适合使用责任链模式来处理。
下面的例子以 View的顺序隐藏、显示及View的动画 演示了事件的传递:
例子中在按下事件分发的按钮时,控件会按照刚开始设置好的顺序依次隐藏、作动画、显示,最后再按下会关闭程序。
说一下实现:
先实现事件协定接口,这个接口用于相互之间的事件流转协议:
public interface IEvent<T> {
public boolean onEvent(@NonNull T obj);
}
EventStub 方法对IEvent接口进行了初步实现,它是事件传递的核心。它会首先询问自己是否消费事件,否则的话会交给下个消费者:
/**
* 责任链抽象类,其中包含下一个实现者的应用
*/
public abstract class EventStub<T> implements IEvent<T> {
protected IEvent mEventStub;
protected T viewStub;
/**
* @param mEventStub 下一级的事件接受者
* @param viewStub 下一级被处理的对象
*/
public EventStub(IEvent mEventStub, T viewStub) {
this.mEventStub = mEventStub;
this.viewStub = viewStub;
}
@Override
public boolean onEvent(@NonNull T obj) {
boolean b = onEventImpl(obj);
if (!b && mEventStub != null)
return mEventStub.onEvent(viewStub);
return b;
}
/**
* @param obj
* @return 代表是否有消费事件
*/
protected abstract boolean onEventImpl(@NonNull T obj);
}
ViewEventStub 是EventStub其中的一个实现,专门用于处理View的隐藏:
/**
* View隐藏
*/
public class ViewEventStub extends EventStub<View> {
/**
* @param mEventStub 下一级的事件接受者
* @param viewStub 下一级被处理的对象
*/
public ViewEventStub(IEvent mEventStub, View viewStub) {
super(mEventStub, viewStub);
}
@Override
public boolean onEventImpl(@NonNull View obj) {
View tempView = obj;
if (tempView.getVisibility() == View.VISIBLE) {
tempView.setVisibility(View.INVISIBLE);
return true;
}
return false;
}
}
AnimationLeftEventStub 也是EventStub的一个实现,用于使View做向左的动画:
AnimationRightEventStub 与AnimationLeftEventStub同理,只是它是执行向右的动画,这里就不再贴代码了。
最后在 CloseEventStub 中也实现了EventStub,它用于处理最后一条消息的展示以及Activity的关闭:
private class CloseEventStub extends EventStub<View> {
/**
* @param mEventStub 下一级的事件接受者
* @param viewStub 下一级被处理的对象
*/ public CloseEventStub(IEvent mEventStub, View viewStub) {
super(mEventStub, viewStub); }
@Override protected boolean onEventImpl(@NonNull View obj) {
if (obj.getVisibility() == View.GONE) { obj.setVisibility(View.VISIBLE);
return true; }
if (!isDestroyed()) { finish();
return true; }
return false; } }
以上就是执行过程中的消费者,我们在Activity中将它们串起来:
EventStub tempStub = new CloseEventStub(null, null);
tempStub = new AnimationRightEventStub(tempStub, findViewById(R.id.view_7));
tempStub = new AnimationLeftEventStub(tempStub, findViewById(R.id.view_6));
tempStub = new ViewEventStub(tempStub, view_5);
tempStub = new ViewEventStub(tempStub, view_4);
tempStub = new ViewEventStub(tempStub, view_3);
sourceStub = new ViewEventStub(tempStub, view_2);
然后由一个按钮触发点击事件,开始传递这个事件:
/**
* 外部触发回调
*
* @param view
*/
public void dismiss(View view) {
//将事件传给责任链头
sourceStub.onEvent(view_1);
}
好了,以上所有的关键步骤就完成了,接下来在点击 dismiss 方法的时候就会将每次的事件依次向下传递,它们会一个个的将事件消费,直至程序关闭。
如果你有好的技术文章想和大家分享,欢迎向我的公众号投稿,投稿具体细节请在公众号主页点击“投稿”菜单查看。
欢迎长按下图 -> 识别图中二维码或者扫一扫关注我的公众号: