Android事件分发小结

 
******** ******** 第一部分: 介绍说明 ******** ********     
 
个人感觉在做交互的时候, 对于Android的按键分发的理解还是比较重要的.
这些内容在<深入理解Android> <Android系统源代码情景分析> 还有一些博客内容中都有写到.
最近想着要仔细的了解一下整体的分发机制, 并且希望能真实的应用在项目中, 所以看了一下InfoQ网站的这篇文章, 感觉写的还不错, 个中有些地方我觉得说的不是很清晰, 但是整体思路自己感觉是理清楚了. 如果发现我理解的有错误, 希望能得到各位的指点(T_T不然会一直错下去的). 
 
相关参考资料:
 
 
******** ********  ******** ********
 
与按键分发有关的类: Activity, View, Window(ViewGroup继承自View, 自定义视图继承自View. ViewGroup特别的有onInterceptTouchEvent()方法, 该方法位于)
 
Activity相关函数:
    dispatchTouchEvent
    onTouchEvent
View相关函数
    dispatchTouchEvent
    onTouch
    onTouchEvent
    onClick
ViewGroup相关函数
    dispatchTouchEvent
    onInterceptTouchEvent
    onTouch
    OnTouchEvent
    onClick
 
******** ******** 按键分发实现细节 ******** ********
 
====>>>> Activity中的按键分发细节:
 
boolean dispatchTouchEvent()
{
    // Window::superDispatchTouchEvent(MotionEvent ev)方法由系统实现
    // 该方法个人感觉存在于PhoneWindow.java类中, 但是文章中没有写的很清楚. 甚至我觉得是有误导... 需要再斟酌.
    // 个人猜测该方法主要用于获取xml文件解析出来的View, 通过区分ViewGroup和普通View, 再执行对应的按键分发逻辑.
    if (getWindow().superDispatchTouchEvent(MotionEvent::ev))
    {
        // 这里表明, 如果dispatchTouchEvent函数返回true, 则表示子类消费过触摸事件
        // 如果子类没有消费过触摸事件, 则执行onTouchEvent()方法
        return true ; 
    }
    else
    {
        return onTouchEvent(MotionEvent::ev) ;
    }
}    
 
总结, 如果子类的dispatchTouchEvent(MotionEvent ev)方法返回了true, 则Activity不再处理该触摸事件. 否则Activity将触摸事件传递给Activity::onTouchEvent(MotionEvent ev)方法处理. 该方法是触摸事件的终点. 
 
====>>>> View中的按键分发细节
    
// Activity会先将触摸事件下发到视图控件中
    // 触摸事件的入口为dispatchTouchEvent()函数
    Window::superDispatchTouchEvent(MotionEvent ev)
    {
        // View处理触摸事件的入口, 也是唯一的入口(个人怎么理解的, 不保证正确性)
        // 其实这里也应该有个遍历, 如果是ViewGroup, 需要先探测所有自孩子的处理结果.
        public boolean dispatchTouchEvent(MotionEvent ev)
        {
            // 对于ViewGroup, 需要先查看是否拦截当前触摸事件, 
            if (this instanceof ViewGroup)
            {
                if (!onInterceptTouchEvent())
                {
                    for (int i = 0 ; i < getChildCount() ; i++)
                    {
                        if (getChildAt(i).dispatchTouchEvent())
                        {
                            return true ;
                        }
                    }
                }
            }
 
            // 这里说明触摸事件监听优先于onTouchEvent并且可以拦截按键分发链条, 从而阻止onTouchEvent函数的执行
            if (null != mTouchListener && mTouchListener.onTouch(MotionEvent::ev))
            {
                return true ;
            }
 
            if (onTouchEvent(MotionEvent::ev))
            {
                return true ;
            }
 
            return false ;
        }
    }
 
    public boolean View::onTouchEvent(MotionEvent ev)
    {
        if (ev.getAction() == MotionEvent.ACTION_UP)
        {
            ….
            return performClick() ;// 该处为猜测
        }
    }
 
    public boolean View::performClick()
    {
        if (null != onClickListener)
        {
            return true ;
        }
 
        return false ;
    }
 
******** ******** 总结 ******** ********
  1. 事件分发的起始点是Activity::dispatchTouchEvent(MotionEvent ev);
  2. dispatchTouchEvent(MotionEvent ev)将事件处理传递给onTouchListener和onTouchEvent()方法, 都返回false表示没有消费
  3. 如果是ViewGroup在dispatchTouchEvent()执行消费逻辑前, 需要递归调用子孩子的dispatchTouchEvent()方法查看子孩子是否消费该事件
  4. onTouchEvent()方法中通过performClick()方法执行了onClickListner的onClick事件
******** ******** END ******** ********
     
posted @ 2016-03-15 16:41  dreamtang  阅读(295)  评论(0编辑  收藏  举报