一种行为模式,为请求创建一个接收者的对象链.这样就避免,一个请求链接多个接收者的情况.进行外部解耦.类似于单向链表结构.
JS 中的事件冒泡,jsp servlet 的 Filter,还有android中的事件传递机制;
传统模式
责任链模式
直接将message丢到链中,让他们自己匹配.
public abstract class AbstractRequest {
private Object object;
public AbstractRequest(Object object)
{
this.object=object;
}
/**
* 具体的内容对象
* @return
*/
public Object getContent()
{
return object;
}
/**
* 获取请求级别
*/
public abstract int getRequestLevel();
}
public class Request1 extends AbstractRequest{
public Request1(Object object) {
super(object);
}
@Override
public int getRequestLevel() {
return 1;
}
}
public abstract class Handler {
public Handler nextHandler;
public void handleRequest(AbstractRequest abstractRequest)
{
if(getHandleLevel()==abstractRequest.getRequestLevel())
{
handle(abstractRequest);
}else {
if(nextHandler!=null)
{
nextHandler.handleRequest(abstractRequest);
}else {
System.out.println("----> 所有的处理对象都不能处理它");
}
}
}
/**
* 每个处理者的对象的具体处理方式
* @param abstractRequest
*/
public abstract void handle(AbstractRequest abstractRequest);
/**
* 每个处着对象处理的级别
* @return
*/
public abstract int getHandleLevel();
}
public class Handler1 extends Handler{
@Override
public void handle(AbstractRequest abstractRequest) {
System.out.println("----handle1 处理请求: "+abstractRequest.getRequestLevel());
}
@Override
public int getHandleLevel() {
return 1;
}
}
public class Client {
public static void main(String[] args) {
//确定链式关系,并拿到链头
Handler handler1 = initChains();
//新建请求,并将请求传给链头
AbstractRequest request2=new Request2("请求2");
handler1.handleRequest(request2);
}
private static Handler initChains() {
Handler handler1=new Handler1();
Handler handler2=new Handler2();
Handler handler3=new Handler3();
handler1.nextHandler=handler2;
handler2.nextHandler=handler3;
return handler1;
}
}
测试结果:
----handle2 处理请求: 2
Activity–>>PhoneWindow–>>decorView(继承FramLayout的根View)–>>ViewGroup(View容器)–>…–>View
以下三篇博客,生动形象,解释了事件分发和事件处理,我想,看完后,大家应该能理解个大概.
这里是吴小龙写的事件分发机制的blog
这里是GcsSloop写的事件分发博客
GCSSloop的事件详解
1.dispatchTouchEvent
事件下发 —View和ViewGroup都有的方法
2.onInterceptTouchEvent
拦截下发的事件,并交给自己OnTouchEvent
处理处理 —ViewGroup才有的方法
3.onTouchEvent
事件上报 —View和ViewGroup都有的方法
4.上面三个方法 ,如果给返回值为true,代表终止传递,
5.事件在传递的时候,会回调用方法中的代码.只有返回true的时候才会触发事件中断.
他们并没有继承同一个抽象类,
上面dispatchTouchEvent
的,就是责任链中的将事件交给下一级处理的.
onInterceptTouchEvent
,就是责任链中,处理自己处理事务的方法.
onTouchEvent
是责任链中 事件上报的事件链.
View中的dispatchTouchEvent
是这样的,主要用于调度自身的监听器和 onTouchEvent。
View的事件的调度顺序是 onTouchListener > onTouchEvent > onLongClickListener > onClickListener 。
ViewGroup 和 ChildView 同时注册了事件监听器(onClick等),由 ChildView 消费。
不论 View 自身是否注册点击事件,只要 View 是可点击的就会消费事件,例如,setClickable(true)
,也将消费事件.
MainActivity.java
代码public class MainActivity extends AppCompatActivity {
private static final String TAG ="MainActivity" ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN){
TLog.error("MainActivity is dispatchTouchEvent");
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
//Log.i(TAG, Static.onTouchEvent+"这么简单都做不了,你们都是干啥的(愤怒).");
TLog.error("MainActivity is onTouchEvent");
}
return super.onTouchEvent(event);
}
}
TouchViewGroup.java
代码/**
* Created by ccj on 2016/12/29.
*/
public class TouchViewGroup extends LinearLayout {
public TouchViewGroup(Context context) {
super(context);
}
public TouchViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TouchViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public TouchViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
TLog.error("TouchViewGroup is onInterceptTouchEvent");
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
TLog.error("TouchViewGroup dispatchTouchEventC");
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
TLog.error("TouchViewGroup is onTouchEvent");
}
return super.onTouchEvent(event);
}
}
/**
* Created by ccj on 2016/12/29.
*/
public class TouchView extends View {
public TouchView(Context context) {
super(context);
}
public TouchView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TouchView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public TouchView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
TLog.error("TouchView dispatchTouchEventC");
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
TLog.error("TouchView is onTouchEvent");
}
return super.onTouchEvent(event);
}
}
public class TLog {
public static final String LOG_TAG = "TLog-->";
public static boolean DEBUG = true;//是否处在debug
public TLog() {
}
public static final void analytics(String log) {
if (DEBUG)
Log.d(LOG_TAG, log);
}
public static final void error(String log) {
if (DEBUG)
Log.e(LOG_TAG, "" + log);
}
public static final void log(String log) {
if (DEBUG)
Log.e(LOG_TAG, log);
}
public static final void log(String tag, String log) {
if (DEBUG)
Log.e(tag, log);
}
public static final void logI(String log) {
if (DEBUG)
Log.i(LOG_TAG, log);
}
public static final void warn(String log) {
if (DEBUG)
Log.w(LOG_TAG, log);
}
}
activity_main.xml
代码
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main"
android:layout_width="match_parent" android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.ccj.viewtouch.MainActivity">
<com.ccj.viewtouch.TouchViewGroup
android:layout_width="200dp"
android:background="@color/colorAccent"
android:gravity="center"
android:layout_height="200dp">
<com.ccj.viewtouch.TouchView
android:background="@color/colorPrimaryDark"
android:layout_width="100dp"
android:gravity="center"
android:layout_height="100dp" />
com.ccj.viewtouch.TouchViewGroup>
FrameLayout>
mdzz…电脑跑了一个eclipse,不想再跑AS了…手写下..
玩法有很多….改变任意一个return
即可,验证你的理论.
当然,理论对应着源码…考虑到篇幅,源码分析,以后会重开一篇博文.
MainActivity is dispatchTouchEvent
TouchViewGroup dispatchTouchEventC
TouchView dispatchTouchEventC
TouchView is onTouchEvent
TouchViewGroup is onTouchEvent
MainActivity is onTouchEvent
责任链模式的核心就是,一条责任链,事件分发,谁消费请求,就停止请求.
应用于:一个请求,多个接受者的情况.
Android 事件分发机制,是责任链的一种变型.由于源码,没有分析完,故此文没有详细展开源码解读.源码分析后期会进行分析.