Android面试路上的拦路虎,ViewGroup的相关源码,你理解多少?

267838-15052F6464826.jpg
ViewGroup某些部分的源码,在学习View的测量以及事件分发的时候,看了很多次。

但是去面试被问到一些细节的问题,却发现还是有很多不理解的地方。

那之后我也很收集很多面试题,没事就看看,现在就分享给大家: 面试合集

此篇文章记录的是面试被问到过的问题,以及我对ViewGroup中一些源码的一些理解。

类型,搞定View的测量模式和大小

在一次面试中被问到:“ViewGroup需要测量子View的时候,传入widthMeasureSpec和heightMeasureSpec,也就是measureChildren()方法里面的参数,它们是什么类型?

我答是int类型(当时心里叽歪,这也能是个问题?),然后面试官再问:“你知道这里为什么用int类型吗?”,

瞬间石化,平时看这部分的内容,真没思考过这个问题。

面试后查资料才知道,用一个int值就可以把测量模式和大小同时搞定,int型是32位,前两位表示mode,后30位表示组件大小的值。

//文中所说的measureChildren()方法
 protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) {
     ......
 }

一个for循环,遍历方式也值得考究

在看View的事件分发时,找出ViewGroup是否有子View接收了事件,需要遍历它所包含的子View,for语句如下

for (int i = childrenCount - 1; i >= 0; i--) { 
   final int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;
   final View child = (preorderedList == null) ? children[childIndex] : preorderedList.get(childIndex);
   ...... 
}

这段代码一直只关注它的作用,某次我突然发现这里是倒序。
为什么源码采用的是倒序?难道谷歌工程师习惯用倒序?
于是查看其它地方,很多都是正序遍历,心想这里肯定有用倒序的理由,于是上网去查。

查到用倒序的原因,是考虑到我们平时的生活习惯,给一块区域设置点击事件的时候,一般都是给最上层的View去设置,而不是给覆盖在它下面的View去设置,倒序遍历,从最上层的View往内去寻找是否有View接收事件,符合日常体验,大概率上来看,如果有View接受事件,倒序是一种更快找出View的遍历方式。

一个功能有很多种实现方式,谷歌工程师总是考虑周全,选择最好的那一种,这就是人家的功力。

数组和List,哪个更适合?

看到过一个View事件分发的学习视频,老师模仿源码的思路去设计这部分的代码,用List去保存了所有View,但是将list转换成数组后才遍历,当时有人问为什么不直接遍历,从List里面取出值也可以,老师回答说这样比较快。

然后我去看相对应的源码,在ViewGroup开始部分就看到了下面这句代码

// Child views of this ViewGroup
   private View[] mChildren;

源码一开始就用了数组去保存子View,ViewGroup源码里多处都使用了数组。平时在开发中,我随手就是一个List,因为方便,可以动态改动数据。看了源码,才意识到在不同场景,应该使用不同保存数据的方法。

在随机访问和迭代数据时,数组是效率较高的,我想这也是ViewGroup里面使用数组的很重要的原因之一,里面的需求也大都是需要遍历访问数据。

以上就是我个人对于ViewGroup的一些理解。最后,还想表达一下源码带给我的个人感悟。

源码带给我的思考

很多大牛总结经验都说,技术的进步是从看源码开始的,我深以为然。看源码并不仅仅让我加深对某个知识的理解,还让我明白,好的代码一定是严谨,准确,讲究性能的。

文章中写的三个地方,都是细节,或许我们不必每处都深究为什么这样写?

但是我们平时就应该多思多想,就像我面试的时不了解,面试官一问就卡壳,平时多积累

发布了99 篇原创文章 · 获赞 5 · 访问量 6253

猜你喜欢

转载自blog.csdn.net/Aerfa789/article/details/103574447