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

责任链模式在Android中的应用相关推荐

  1. Android 架构之路(4)责任链模式在项目中的实际使用

    文章目录 前言 责任链模式定义 UML 类图: Demo 实现方式一: UML 类图: Demo 实现方式二: 项目实践 实现方式一: 实现方式二: 总结 前言 责任链模式(职责链模式)的运用在项目中 ...

  2. 责任链模式在SpringAOP中的使用

    当一个对象在一条链上被多个拦截器拦截处理时,我们这样的设计模式称为责任链模式,它用于一个对象在多个角色中传递的场景. SpringAOP就是利用动态代理和责任链模式实现的,当一个切面有多个织入时,这些 ...

  3. 责任链模式 php,编程中的那些套路——关于责任链模式

    该文章属于<编程中的那些经典套路--设计模式汇总>系列,并且以下内容基于语言PHP 今天来谈谈责任链模式,乍一听责任链模式好像很高级的一样,但是相信我,其实每位天朝的同学都十分熟悉这个模式 ...

  4. 设计模式中的车轮战-责任链模式

    责任链模式在Android中的应用莫过于事件分发了,ViewGroup对事件分别给子View,从ViewTree的顶部至上而下地进行处理,直到事件被消化为止,这种方法在Android广播中也能看到 责 ...

  5. android 链式结构,Android 架构师之路10 设计模式之责任链模式

    1. 责任链模式概念 1.1 介绍 客户端发出一个请求,链上的对象都有机会来处理这一请求,而客户端不需要知道谁是具体的处理对象.这样就实现了请求者和接受者之间的解耦,并且在客户端可以实现动态的组合职责 ...

  6. java设计模式之责任链模式以及在java中作用

    责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链上的哪一个 ...

  7. 【深入设计模式】责任链模式—责任链模式及责任链模式在源码中的应用

    文章目录 1. 责任链模式 1.1 责任链模式简介 1.2 责任链模式结构 1.3 责任链模式示例 2. 责任链模式在源码中的应用 2.1 Servlet 中的责任链模式 2.2 Spring 中的责 ...

  8. 责任链模式在复杂数据处理场景中的实战

    相信大家在日常的开发中都遇到过复杂数据处理和复杂数据校验的场景,本文从一线开发者的角度,分享了责任链模式在这种复杂数据处理场景下的实战案例,此外,作者在普通责任链模式的基础上进行了升级改造,可以适配更 ...

  9. [转]《JAVA与模式》之责任链模式

    http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html 在阎宏博士的<JAVA与模式>一书中开头是这样描述责 ...

最新文章

  1. 如何保护你写的 Python 代码?
  2. 以赛促学,飞桨助力大学生智能车竞赛升级
  3. 屌丝逆袭高富帅之JAVA之路
  4. 从原型链看DOM--Node类型
  5. 考研编程练习----快速排序
  6. python2x 安装 psutil
  7. 频谱知识图谱:面向未来频谱管理的智能引擎人工智能技术与咨询
  8. This dependency was not found: * !!vue-style-loader!css-loader?……解决方案
  9. struts2 配置 自学练习 list jsp页输出 中文转英文首字母
  10. [nRF51822] 1、一个简单的nRF51822驱动的天马4线SPI-1.77寸LCD彩屏DEMO
  11. 《云计算核心技术剖析》读书笔记之一
  12. 3399 android root,RK3399 android8.1 app获取root权限
  13. 中国天气网 天气预报API 国家气象局 根据城市名称抓取城市ID,XML格式、JSON格式、图片代码
  14. 苹果手机白屏_岳瀚:Iphone手机维修简单总结
  15. js中动态获取页面的高度和宽度的方法总结
  16. MoviePy合成视频没有声音
  17. 什么是超链接:下划线、样式、字体颜色、代码怎么做?
  18. 【问题】Adobe安装程序初始化失败
  19. 前端面试重要问题总结(前端100问小结)(六)
  20. [c++] insert和emplace的区别

热门文章

  1. typename的作用
  2. C语言判断计算机存储是大端还是小端
  3. 工作后和在学校最大的区别是什么?
  4. linux模块加载和模块卸载时出现的问题
  5. oracle联合主键怎么找,Oracle数据库联合主键
  6. ubuntu常见问题
  7. vmware与windows共享文件夹
  8. java调用sql返回list_Spring JdbcTemplate实现有java.sql.ResultSet结果集返回的存储过程调用 | 学步园...
  9. mysql 排序num_MySQL 实现row_number() 分组排序功能
  10. mit数据集_DriveSeg:动态驾驶场景分割数据集