开头
25岁那年,我从京东离职,入职百度。
在百度认识了当时的架构师久哥(T9级别),因为他的一番话,彻底改变了我的职业生涯,短短三年的时间,我从一枚普通程序员成长为别人眼中的技术大咖。
当时因为业务需要,也承蒙久哥照顾,他跟我说过这样一段话:
他问,“如果用5年的时间学习数据库,你能不能成为这个领域的专家?”
我说,“应该可以吧”
他说,“你现在25,5年后也才30,30岁就能成为某个领域的专家,为什么不去做呢?你看看周围有多少30岁的人还一事无成,而那个时候的你已经是数据库专家了。”
当时的我,刚刚进入别人梦寐以求的BAT,处于各种浮躁的时期,虽然每天也在学习,看起来也很努力,但是效果极其有限,今天想学大数据,明天想学云计算,后天又要研究机器学习,心境变化无常,不知道自己未来究竟该是什么样。
面试官:说说view中的事件分发?
android中事件分发机制是android中常见的问题,一般大家都知道view的分发事件是从view的Viewgroup(Parent)#dispatchTouchEvent
到Viewgroup(Parent)#onInterceptTouchEvent
再到View#dispatchTouchEvent
,然后到view的onTouchEvent
,最后又回到了Viewgroup(Parent)#onTouchEvent
。如果大家记不住方法名,可以直接说先是parent的分发到拦截再到view的分发,再到view的消费,最后到parent的消费
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;
}
紧接着在在后面又会调用了:
这句只有在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高级工程师系统学习资料的,我可以免费分享给大家,需要完整版的朋友,【点这里可以看到全部内容】。
《系列学习视频》
《系列学习文档》
《我的大厂面试之旅》
》**
[外链图片转存中…(img-t7ok84Nc-1621871216486)]
《我的大厂面试之旅》
[外链图片转存中…(img-c2wn0NDd-1621871216490)]