随我一起慢慢揭开Andoird里事件分发机制的神秘面纱
admin
2023-02-09 22:00:05
0

转载好文章:

    http://blog.csdn.net/chunqiuwei/article/details/41084921

    


 学了这么久的Android,面试也常被问到事件分发机制,但总感觉对这个机制还是不清不楚.突然之间

 翻了一下李刚的,突然有了一些感悟,所以就立马记下来:


一、监听与回调

   第一,要明白和事件相关的3个概念:事件源,事件,事件监听器.

   事件源:就是事件作用的对象

   事件:就是事件本身,可以是点击,长按,移动等等,就是XxxEvent.

   事件监听器:就是Listener,一般写成内部类的形式,说白了,就是一个类,而这个类往往是事件源

           内部的接口实现类。 


   第二,上总结得很到位:Android中的事件处理机制可以分为两大类,监听回调.

   监听:就是给控件添加一个监听器,即addXxxListener(new XxxListener(){...}),事件源本身不直

      接处理,而是交由事件监听器进行处理.

   回调:当事件作用在事件源的时候,事件源本身会触发一些自己的方法,自己来处理事件.但往往事件

     源的这些方法是封装在事件源对象的内部的,用户看不见.这也就是为什么需要有监听器的原

     因,让用户知道事件源发生了什么事件.通常在自定义控件的时候,就需要复写和Touch相关的

     事件,同时抽取监听器接口,让用户去实现.


-----------------------------------------------------------------------------------------

   举个小例子:

      假如有这样一个需求:点击一下Button,打印一条日志.

      那么有2种实现方式

      第1种实现方式-为Button设置监听器

         Button.setOnClickListener(new OnClickListener(){

         onClick(View view)

           {

              Log...

            } 

         }); 

      第2种实现方式-继承Button,自定义一个MyButton

         定义的时候,复写Button的onTouchEvent方法,在里面打印日志.

      

     那么,现在又有一个需求:点击一下Button,弹出一个吐司.

      如果采用第1种方式,只要修改一下onClick里的代码.

      如果采用第2种方式,那么1种办法是再创建一个Button的子类,另外一个方法就是修改原来

        MyButton的onTouchEvent方法,但是这样一来又不能满足开始的需求了.

      

      所以到这里,监听与回调的区别也就不言而喻了吧.

       1)监听只是组件的作者在写回调方法时,暴露给用户的一个接口,这样用户可以实现接口,

        达到自身的需求,最终用户实现的接口里的方法在组件的回调方法里会被回调。

       

二、结合2.3.3中View的源码,再谈监听与回调 

   1.View的dispatchTouchEvent方法

    我之前一直没有搞清楚View的dispatchTouchEvent的返回值的作用,现在明白了,

    返回true,作用在View上的触摸事件(包括Button的点击事件)就会生效;

    返回false,作用在View上的触摸事件就失效。

    但具体dispatchTouchEvent方法又在哪里被调用了呢(?????????????) 

     public boolean dispatchTouchEvent(MotionEvent event) {
           。。。
            if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
                    mOnTouchListener.onTouch(this, event)) {
                return true;
            }
            return onTouchEvent(event);
     }

   

       2)监听是先判断的,所以监听比回调的优先级要高。先判断listener.onTouch的返回值

        ,否则就return onTouchEvent(event)将事件交由组件的onTouchEvent回调方法进行处理。

     

     所谓View的事件分发,解决的问题就是事件是由用户处理还是View自身处理

       

三、结合2.3.3中ViewGroup的源码,再谈监听与回调       

     

    由于ViewGroup的dispatch事件源码过多,我就不一一写了,大致地去描述一下。

     ViewGroup的dispatch事件干的事:


     先弄一个变量来缓存可能会捕捉并处理事件的View,target.

     在点击ev.getAction == MotionEvent.Action_Down的事件里

       根据onIntercept事件判断自己需不需要拦截事件,如果不拦截,则遍历ViewGroup里的

     每个子View,通过计算子View的矩形区域来判断点击事件的坐标有没有落在子View上,如果点

     击事件的坐标落在子View并且子View捕捉并处理事件,那么target就等于这个子View。


        判断target是否为null

            如果为null,则调用ViewGroup的父类的dispatch事件,也就是把ViewGroup当作

         View来处理。

            如果不为null,则交由target.dispatch事件进行处理。


    所谓ViewGroup的事件分发,解决的问题就是事件到底是由哪个View来处理。



四、FrameLayout的事件分发机制

    我们都知道,ViewGroup的事件传递顺序是由父控件往子控件传递,但是假如是FrameLayout的两

    个子控件重叠在一起,并且两个子控件没有包含(父子)关系,那么事件的传递顺序是怎样的呢

   

    其实这个Android源码里已经说得十分地清楚了,

// Scan children from front to back.

    也就是从上往下查找,自然事件也是从上往下传递。


    1)在做《风口》项目时,我也遇到过这种问题:

        明明点击的地方什么也没有,但是事件却被响应了。我将布局看来看去,想了很久,突然

    明白这就是事件分发导致的。FrameLayout的上层Layout点击的位置没有控件响应事件,但是在下

    一层的Layout中,鼠标点位的位置有控件响应。这种解释了这种见鬼的原因!

    2)小资钱包首页,“马上抢购”按钮和它所在的父布局响应同样的事件。

     第1种方法:给2者注册同一个监听器 

     第2种方法:屏蔽Button对事件的响应,只注册父布局的监听。(即怎么让按钮可点击但是不响

          应点击事件)

          复写Button onIntercept方法返回false.

    

      

相关内容

热门资讯

德国总理:美国正在被伊朗羞辱 德国之声4月27日报道,德国总理默茨在访问一所学校时表示,在当前的持续冲突中,伊朗领导层正试图羞辱美...
理响中国|“长”歌以行,风云激... 光阴如梭,东方潮阔。这里是中国的长三角,世界的长三角。无论过去、现在还是未来,这片土地都因时代而生,...
白宫:特朗普及其国安团队开会讨... 新华社华盛顿4月27日电 美国白宫新闻秘书莱维特27日在记者会上证实,总统特朗普及其国家安全团队当天...
人民日报刊文:日本放开杀伤性武... 日本放开杀伤性武器出口推高地缘冲突风险(国际论坛)常思纯《人民日报》(2026年04月28日 第 0...
医疗保障法草案二审:明确生育保... 满足多样化健康保障需求本报记者 彭 波4月27日,医疗保障法草案二审稿提请十四届全国人大常委会第二十...
天津一景区发生自转旋翼机事故1... 澎湃新闻记者 吕新文中国民用航空华北地区管理局4月22日公布《豪客通航“10•1”天津长芦汉盐旅游区...
卡塔尔埃米尔与美国总统特朗普通... 当地时间24日,卡塔尔埃米尔塔米姆与美国总统特朗普通电话,重点就中东地区局势以及伊朗与美国谈判问题交...
男子30年前被扣押2859克黄... 澎湃新闻记者 王鑫家住辽宁省大连市的潘永嘉近日向澎湃新闻反映称,三十年前,他在大连周水子机场被盖州市...
商务部:取消反制欧盟两家金融机... 中华人民共和国商务部令二〇二六年 第1号鉴于欧盟已取消对中国两家金融机构的制裁措施,现公布《关于取消...
过去24小时共有5艘船只通过霍... 总台记者当地时间24日获悉,过去24小时内,共有5艘船只通过霍尔木兹海峡,其中包括一艘伊朗油轮。(总...