曾听过很多人说AndroID学习很简单,做个App就上手了,工作机会多,毕业后也比较容易找工作。这种观点可能是很多AndroID开发者最开始入行的原因之一。
在工作初期,工作主要是按照业务需求实现App页面的功能,按照设计师的设计稿实现页面的效果。
在实现的过程中,总是会被提如下的需求:
这个字能不能大点或者醒目点儿?
感觉颜色和设计稿有差别,能不能再调调?
怎么老是崩溃啊,行不行啊?
…
所以,工作过一年后你会发现,自己的工作重点就是**将找各种各样的组件、框架,拖拖拽拽,改改样式。**在极端情况下出现了问题后(比如部分机型上崩溃,加载图片慢),也不知道该如何解决!都不好意思说自己是搞技术的。
面试官:说说vIEw中的事件分发?androID中事件分发机制是androID中常见的问题,一般大家都知道vIEw的分发事件是从vIEw的VIEwgroup(Parent)#dispatchtouchEvent
到VIEwgroup(Parent)#onIntercepttouchEvent
再到VIEw#dispatchtouchEvent
,然后到vIEw的ontouchEvent
,最后又回到了VIEwgroup(Parent)#ontouchEvent
。如果大家记不住方法名,可以直接说先是parent的分发到拦截再到vIEw的分发,再到vIEw的消费,最后到parent的消费
这样回答肯定是很浅显的,因为没有说出是否拦截、是否分发、是否消费的各种条件,没有涉及到各种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的dispatchtouchEvent和vIEw的ontouchEvent事件的处理流程,上面已经分析了想要vIEw能执行到vIEw的touch事件,那么必须要求vIEw的dispatchtouchEvent
返回true,而dispatchtouchEvent
返回true要么是dispatchtouchEvent
直接返回true或者vIEw的ontouchEvent
返回true。如果从效率上看,直接将dispatchtouchEvent
返回true就ok,而不需要再去关心ontouchEvent
方法。
关于拦截无非就是拦截或不拦截,而拦截的条件是返回true,不拦截是返回false或返回super.onIntercepttouchEvent,默认的super是返回false的,因此可以用super表示不拦截
vIEwgroup拦截实际是通过在dispatchtouchEvent
方法中,设置intercepted变量,如果在拦截方法里面返回true,那么intercepted为true,如果为true则在action_down的时候mFirsttouchTarget=null,那么此时是直接调用dispatchtransformedtouchEvent
传入的child=null,因此将事件交给了super.dispatchtouchEvent
,此时把它当成一个vIEw来处理了。
AndroID高级架构师进阶之路
题外话,我在阿里工作多年,深知技术改革和创新的方向,AndroID开发以其美观、快速、高效、开放等优势迅速俘获人心,但很多AndroID兴趣爱好者所需的进阶学习资料确实不太系统,完整。今天我把我搜集和整理的这份学习资料分享给有需要的人,若有关AndroID学习进阶可以与我在AndroID终极开发交流群一起讨论交流。 点击这里前往我的腾讯文档领取资料 的同时,还可以加入一个好的学习交流圈,何乐而不为呢?加入我们和我们一起吧!!
AndroID进阶知识体系学习脑图AndroID进阶高级工程师学习全套手册对标AndroID阿里P7,年薪50w+学习视频大厂内部AndroID高频面试题,以及面试经历droID阿里P7,年薪50w+学习视频**
[外链图片转存中…(img-YlxKlh0Q-1618537221739)]
大厂内部AndroID高频面试题,以及面试经历 总结以上是内存溢出为你收集整理的android适配器ui,2021年Android面经分享,面试总结全部内容,希望文章能够帮你解决android适配器ui,2021年Android面经分享,面试总结所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)