Android中的责任链模式分析

来源:互联网 发布:淘宝品牌直营是真的吗 编辑:程序博客网 时间:2024/06/04 23:32


本篇是 SAHADEV 是第二篇投稿不同于之前的译文,今天他亲自编写了示例来阐述责任链模式。


SAHADEV 的博客地址:http://blog.csdn.net/sahadev_


写在前面


责任链其实在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做向左的动画:




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 方法的时候就会将每次的事件依次向下传递,它们会一个个的将事件消费,直至程序关闭。




如果你有好的技术文章想和大家分享,欢迎向我的公众号投稿,投稿具体细节请在公众号主页点击“投稿”菜单查看。


欢迎长按下图 -> 识别图中二维码或者扫一扫关注我的公众号: