责任链模式在Android中的应用

*本篇文章已授权微信公众号 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值