2021年阿里 腾讯 快手offer都已拿到!HR的话扎心了
## 面试官:说说view中的事件分发?
android中事件分发机制是android中常见的问题,一般大家都知道view的分发事件是从view的`Viewgroup(Parent)#dispatchTouchEvent`到`Viewgroup(Parent)#onInterceptTouchEvent`再到`View#dispatchTouchEvent`,然后到view的`onTouchEvent`,最后又回到了`Viewgroup(Parent)#onTouchEvent`。如果大家记不住方法名,可以直接说**先是parent的分发到拦截再到view的分发,再到view的消费,最后到parent的消费**
![](http://www.icode9.com/i/li/?n=2&i=images/20210706/1625575388971578.jpg)
### viewgroup分发
这样回答肯定是很浅显的,因为没有说出是否拦截、是否分发、是否消费的各种条件,没有涉及到各种action的分发情况,上面说的默认分发只是针对action_down的,因为`view/viewgroup`各种super调用都是不进行分发、拦截、消费的,所以在没找到处理touch事件的view时候,是一直往上层view传递的,一直传到activity里面,下面我们再来整理一下:
> 如果viewgroup不进行分发,那么`action_down`、`action_move`和`action_up`只会执行到viewgroup的`dispatchTouchEvent`,不分发的条件是`dispatchTouchEvent`直接返回true或false,true和false的区别是true会执行`action_down`、`action_move`和`action_up`,而如果直接返回false只会执行到action_down。并且后续的viewgroup的`onInterceptTouchEvent`后续方法都不会被执行到。
关于为什么view/Viewgroup的`dispatchTouchEvent`返回true的时候三个action都能执行到,而返回false的话,只能执行到action_down,这个需要到view/Viewgroup的父类中`dispatchTouchEvent`找答案,该方法中会在action_down的时候调用`dispatchTransformedTouchEvent`方法,而该方法是通过子view的dispatchTouchEvent方法的返回值来决定父类的`dispatchTransformedTouchEvent`方法的返回值,而`dispatchTransformedTouchEvent`的返回值会决定`mFirstTouchTarget`是否为空,所以在action_down的过程中实际中通过子view的`dispatchTouchEvent`方法返回值来确定`mFirstTouchTarget`是否为空。这里贴出viewgroup中`dispatchTransformedTouchEvent`方法的删减代码:
```
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
View child, int desiredPointerIdBits) {
------------------
//省略了cancel部分的代码
------------------------
//如果child为空,直接调用自己的dispatchTouchEvent方法,此时自己就相当于一个view,touch事件走自己的
if (child == null) {
handled = super.dispatchTouchEvent(transformedEvent);
} else {
final float offsetX = mScrollX - child.mLeft;
final float offsetY = mScrollY - child.mTop;
transformedEvent.offsetLocation(offsetX, offsetY);
if (! child.hasIdentityMatrix()) {
transformedEvent.transform(child.getInverseMatrix());
}
//返回值直接通过孩子来获取返回值
handled = child.dispatchTouchEvent(transformedEvent);
}
transformedEvent.recycle();
return handled;
}
```
所以如果view/viewgroup的`dispatchTouchEvent`方法返回false,表示在action_down的时候,父类的`dispatchTransformedTouchEvent`方法返回false;如果返回true会调用`addTouchTarget`方法,给`mFirstTouchTarget`设置值:
```
private TouchTarget addTouchTarget(@NonNull View child, int pointerIdBits) {
final TouchTarget target = TouchTarget.obtain(child, pointerIdBits);
target.next = mFirstTouchTarget;
mFirstTouchTarget = target;
return target;
}
```
紧接着在在后面又会调用了:
![](http://www.icode9.com/i/li/?n=2&i=images/20210706/1625575388846657.jpg)
这句只有在view/viewgroup的`dispatchTouchEvent`返回false的时候,才会走这里,所以后面的`action_move`和`action_up`都会走这里,而此时传入的child=null,从上面代码可以看到,直接调用了父类的`dispatchTouchEvent`方法。所以从这里不难看出在view/viewgroup的`dispatchTouchEvent`返回false的时候直接调用了父类的`dispatchTouchEvent`方法,因此只有action_down事件。
## 面试官:如果我只想有view的拖拽事件,而不想要view的点击事件,让你重写这个view的拖拽怎么设计
其实这道题考察大家对view的dispatchTouchEvent和view的onTouchEvent事件的处理流程,上面已经分析了想要view能执行到view的touch事件,那么必须要求view的`dispatchTouchEvent`返回true,而`dispatchTouchEvent`返回true要么是`dispatchTouchEvent`直接返回true或者view的`onTouchEvent`返回true。如果从效率上看,直接将`dispatchTouchEvent`返回true就ok,而不需要再去关心`onTouchEvent`方法。
### viewgroup拦截
**关于拦截无非就是拦截或不拦截,而拦截的条件是返回true,不拦截是返回false或返回super.onInterceptTouchEvent,默认的super是返回false的,因此可以用super表示不拦截**
viewgroup拦截实际是通过在`dispatchTouchEvent`方法中,设置intercepted变量,如果在拦截方法里面返回true,那么intercepted为true,如果为true则在action_down的时候mFirstTouchTarget=null,那么此时是直接调用`dispatchTransformedTouchEvent`传入的child=null,因此将事件交给了`super.dispatchTouchEvent`,此时把它当成一个view来处理了。
## 面试官:有个viewgroup,里面有个view,如果view在dispatchTouchView中不分发事件,并且只在action_move中拦截touch事件向下分发,说说viewgroup到view的各个action是如何分发的?
#### 如何成为Android高级架构师!
架构师必须具备抽象思维和分析的能力,这是你进行系统分析和系统分解的基本素质。只有具备这样的能力,架构师才能看清系统的整体,掌控全局,这也是架构师大局观的形成基础。 **你如何具备这种能力呢?一是来自于经验,二是来自于学习。**
架构师不仅要具备在问题领域上的经验,也需要具备在软件工程领域内的经验。也就是说,架构师必须能够准确得理解需求,然后用软件工程的思想,把需求转化和分解成可用计算机语言实现的程度。经验的积累是需要一个时间过程的,这个过程谁也帮不了你,是需要你去经历的。
**但是,如果你有意识地去培养,不断吸取前人的经验的话,还是可以缩短这个周期的。这也是我整理架构师进阶此系列的始动力之一。**
***
##### 成为Android架构师必备知识技能
![](http://www.icode9.com/i/li/?n=2&i=images/20210706/1625575388268362.jpg)
##### 对应导图的学习笔记(由阿里P8大牛手写,我负责整理成PDF笔记)
![](http://www.icode9.com/i/li/?n=2&i=images/20210706/1625575389540955.jpg)
##### 部分内容展示
**《设计思想解读开源框架》**
* **目录**
![](http://www.icode9.com/i/li/?n=2&i=images/20210706/1625575389917273.jpg)
* **热修复设计**
![](http://www.icode9.com/i/li/?n=2&i=images/20210706/1625575389515197.jpg)
* **插件化框架设计**
![](http://www.icode9.com/i/li/?n=2&i=images/20210706/1625575390655647.jpg)
**《360°全方面性能优化》**
![](http://www.icode9.com/i/li/?n=2&i=images/20210706/1625575390678228.jpg)
* **设计思想与代码质量优化**
![](http://www.icode9.com/i/li/?n=2&i=images/20210706/1625575390870399.jpg)
* **程序性能优化**
![](http://www.icode9.com/i/li/?n=2&i=images/20210706/1625575390456110.jpg)
**本文在开源项目:[【腾讯文档 】](https://docs.qq.com/doc/DSkNLaERkbnFoS0ZF)中已收录,里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…**