*本篇文章已授权微信公众号 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;    }    @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做向左的动画:

public class AnimationLeftEventStub extends EventStub<View> {    private boolean result = true;    /** * @param mEventStub 下一级的事件接受者 * @param viewStub 下一级被处理的对象 */    public AnimationLeftEventStub(IEvent mEventStub, View viewStub) {        super(mEventStub, viewStub);    }    @Override    protected boolean onEventImpl(@NonNull View obj) {        if (result) {            ObjectAnimator anim = ObjectAnimator.ofFloat(obj, "x", -400);            anim.setDuration(1000);            anim.addListener(new Animator.AnimatorListener() {                @Override                public void onAnimationStart(Animator animation) {                }                @Override                public void onAnimationEnd(Animator animation) {                    result = false;                }                @Override                public void onAnimationCancel(Animator animation) {                }                @Override                public 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);        }        @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方法的时候就会将每次的事件依次向下传递,它们会一个个的将事件消费,直至程序关闭。

完整的程序请参见:https://git.oschina.net/sahadev/Chain-of-Responsibility.git

更多相关文章

  1. 再论Handler—Handler事件分发、Handler线程切换原理解析
  2. Android(安卓)事件处理详解(二) —— 基于回调的事件处理
  3. Android中的事件处理研究
  4. 自定义View之滑动事件
  5. Android(安卓)View从源码的角度分析事件的注册和接收
  6. Android如何通过parcelable实现跨进程之间多态的类型的传递。
  7. [Android] 图像处理整合之处理ColorMatrix和Intend传递路径显示
  8. Android的事件处理
  9. Android中序列化的Parcelable与Serializable区别及其AS插件

随机推荐

  1. android,handler实现两个线程通信
  2. Android(安卓)开发技术周报 Issue#281
  3. android 物理按键
  4. Android深入浅出系列课程---Lesson7 LLY1
  5. Android(安卓)中 PopupWindow的用法 汇总
  6. Android(安卓)- 常见错误的解决方法
  7. Android(安卓)Google Map实例 - 发布Andr
  8. 那些年,在Fragment中犯的错
  9. 一个APK反编译利器Apktool(android汉化)
  10. Android实现QQ分享及注意事项