软件测试布道师的江湖

深耕软件测试领域,定期分享技术干货,一起成长!

Android事件分发机制

      今天coding,无意写了个小bug出来,dialog去dismiss的时候不起作用,后来排查到是在dispatchTouchEvent中去show dialog时,有可能会创建两个Dialog,然后监听回调还是第一个的,当dismiss的时候,mDocorView是null的,所以dismiss的时候,就直接return掉,没有执行dismiss的逻辑。总结来说这个bug还是因为自己对事件分发理解的不透彻,正好之前没总结过,所以就写一遍博客记录下,方便自己之后查看。

  首先我们直接把View和ViewGroup一起来看,写一个demo,demo很简单,自定义两个View:一个继承Button(TestEventBtn),一个继承LinearLayout(TestEventDispatchLayout),然后这个Button放到TestEventDispatchLayout上,网上大部分的例子应该都是这个做demo的吧。之后就分别实现他们的dispatchTouch、onTouchEvent、onInterceptTouchEvent(只有ViewGroup有)、另外在Activity中把两个控件的onClickListener也加上。

  1)首先我们来做做实验,通过实验肯定有些情况不明白的,再看代码。

  •  点击TestEventDispatchLayout除了TestEventBtn之外的区域:

从上面的日志我们可以看出touch事件首先是在被点击到的区域传递。从Activity到TestEventDispatchLayout传递了ACTION_UP和ACTION_DOWN事件,最后被TestEventDispatchLayout的onClick把事件吃掉,我们改动下,不设置onClickListener看看会怎么样:

  • 点击TestEvent:

  • 点击TestEventDispatchLayout之外的区域:

上面三种情况都是从MainActivity 的dispatchTouchEvent开始的,我们可以debug抓个trace看下点击事件传递路径:

从这个堆栈,我们大致可以看出,最下面应该是硬件层会不停的检测是否有touch事件,当有touch事件时,会通过InputEventReceiver去dispatchInputEvent,接着中间这一大块都是在ViewRootImpl中的处理。

基本都是对事件的处理和传递,最后会传递到PhoneWindow的DecorView中dispatchTouchEvent,它的源码是:

熟悉代码的同学可能会对这个Callback特别熟悉,Activity就实现了这个callback,因此这里的Callback就是Activity,好了,这就验证了上面的都是从Activity的dispaTouchEvent开始了。

从网上找了一个哥们的图,如下,能比较直观的理解事件传递过程。

一个View就像一棵树一样,touch事件从根依次的传递到叶子的view。这也是android设计巧妙的地方,用了组合设计模式。

2)

 

posted @ 2019-09-05 23:15  布道师玄柯  阅读(544)  评论(0编辑  收藏  举报