*本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布
责任链其实在Android中出现的频率还蛮高的,事件传递就是一种责任链机制。接下来我为大家介绍在开发应用时责任链的用处:
- 1.触摸事件的应用。
- 2.响应事件的应用。
何为责任链?责任链说白了就是一个事件传递的链条,一般这个链条上有很多个事件消费者,每个事件消费者都有机会接收并消费事件:
第一个对象如果可以处理,则处理后返回,如果不能处理,则将事件传递下一个对象处理,以此推类。
那么它究竟在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;}@Overridepublic 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);}@Overridepublic boolean onEventImpl(@NonNull View obj) {View tempView = obj;if (tempView.getVisibility() == View.VISIBLE) {tempView.setVisibility(View.INVISIBLE);return true;}return false;}
}
AnimationLeftEventStub也是EventStub的一个实现,用于使View做向左的动画:
public class AnimationLeftEventStub extends EventStub<View> {private boolean result = true;/*** @param mEventStub 下一级的事件接受者* @param viewStub 下一级被处理的对象*/public AnimationLeftEventStub(IEvent mEventStub, View viewStub) {super(mEventStub, viewStub);}@Overrideprotected boolean onEventImpl(@NonNull View obj) {if (result) {ObjectAnimator anim = ObjectAnimator.ofFloat(obj, "x", -400);anim.setDuration(1000);anim.addListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {result = false;}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {}});anim.start();}return result;}
}
AnimationRightEventStub与AnimationLeftEventStub同理,只是它是执行向右的动画,这里就不再贴代码了。
最后在CloseEventStub中也实现了EventStub,它用于处理最后一条消息的展示以及Activity的关闭:
private class CloseEventStub extends EventStub<View> {/*** @param mEventStub 下一级的事件接受者* @param viewStub 下一级被处理的对象*/public CloseEventStub(IEvent mEventStub, View viewStub) {super(mEventStub, viewStub);}@Overrideprotected 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方法的时候就会将每次的事件依次向下传递,它们会一个个的将事件消费,直至程序关闭。
完整的程序请参见:https://git.oschina.net/sahadev/Chain-of-Responsibility.git