浅谈android应用之事件分发
1. 前言
在android中,事件有多种种类,比如说最常见的屏幕的点击事件,除此之外,还有外接设备的信号事件,如鼠标,键盘,遥控器的信号事件。这里就拿最常见的屏幕的点击事件来说事。点击屏幕的时候,首先是硬件驱动采集点击屏幕时候的信息,硬件驱动采集到了之后,它本身不会做消费这些数据信息,它会往native层抛出这些信息,但最终native层会将这些信息再抛往上层framework层进行处理。这个过程可以研究系统服务IMS,这里不再详述。
到这一步,就到了我们通常所述的事件分发,即应用层的事件分发的过程。
2. 流程图
以下是事件分发的流程图,先大体看看在应用层事件分发与事件被消费的过程:
可以看出整个流程呈现出U型状,可以大体总结出事件是往下分发,往上消费,接下来将对这个过程进行详细分析。
3. Activity
点击事件在应用层首先到Activity上,所以我们从Activity的分发方法看:
=============/frameworks/base/core/java/android/app/Activity.java ===============
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
1.如果是down,说明是一个新的事件,初始化UI(空实现方法,没有太大实际意义)
2.调用PhoneWindow的superDispatchTouchEvent 方法,把事件从Activity 分发到PhoneWindows,再到DecorView,再到ViewGroup,View,如果中间不被中断拦截的正常情况下。(这个过程是事件分发核心方法,这个可以结合我的文章视图原理辅助理解)如果子View没有消费该事件,则调用自身的onTouchEvent尝试处理。
3.如果上面分发过程都没有消费事件,则最终由Activity的onTouchEvent方法消费事件。
4. ViewGroup
ViewGroup的分发方法主要作用是确定那个View消费事件
1.判断是否进行事件拦截,
2.根绝拦截方法的返回结果进行处理
如果进行了拦截,则会调用到super.dispatchTouchEvent(event),最终会调用到View类的dispatchTouchEvent(event)
如果没有进行拦截,则会对自己内部的所有子View进行判断,是否有焦点,是否在事件坐标范围之内等等一系列,然后调用该View的dispatchTouchEvent(event)(这里补充一下,这个子View可以是ViewGroup类型的也可以是View类型的。所以如果是viewGroup类型的还会把这个流程走一遍,直到找到我们需要的View)
还需要注意的是事件传递在viewgroup这个过程才有拦截事件的方法!
5. View
View类型的分发方法和ViewGroup的作用不一样,主要是确定怎么消费事件
判断mOnTouchListener.onTouch(this, event)的返回值,如果返回true,后边onTouchEvent(event)就不会响应了,如果返回false,则会调用自身onTouchEvent(event)消费事件,如果onTouchEvent返回false,则回到上以及viewgroup的onTouchEvent进行处理,以此类推,直到最后事件被消费。
上一篇: 组件之间的通信
下一篇: Spring入门之事件处理