View.findViewById是深度优先的

发布时间:2019-07-02 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了View.findViewById是深度优先的脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

我喜欢用简单的单词来给XMl中的元素加id,比如一个View里面要展示一行文字和一个图标,那么,展示文字的就叫text,展示图标的就叫icon

像这样:

<LinearLayout>
    <TextView
        andROId:id="@+id/text"/>
    <ImageView
        android:id="@+id/icon"/>
</LinearLayout>

然后我就在想,在同一个布局文件中,是不允许同名(同id)的,不然就会报错,像这样:

<LinearLayout>
    <TextView
        android:id="@+id/text"/>
    <ImageView
        android:id="@+id/text"/> <!-- Error: text作为id已经存在了 -->
</LinearLayout>

但是在有层次嵌套的布局中,允许同名的id,那么findViewById会找到哪一个呢?

为了得到这个问题的答案,我首先去grepcode上搜了一下ViewGroup.findViewById()的码实现

View.findViewById是深度优先的

可以看到,ViewGroup去findViewById的时候,先把自己的子元素都拿出来,遍历他们,然后调用它们的findViewById,想象一下,如果子元素是个View,那么id只要配对上了,就直接返回了,如果子元素是个ViewGroup,那么就会继续调用子ViewGroup的这个方法。显然,这是一个深度优先的find。

为了验证这个深度优先,我构造了一个场景。先用文字来描述一下:在LinearLayout里面有一个ListView和一个TextView(这个TextView的id是text),然后ListView用数据去填充一些item,item的布局里面都是id为text的TextView。

然后,我在onCreate的时候去findViewById(R.id.text),会获取到哪一个TextView呢?
a.获取到LinearLayout里面的TextView
b.获取到ListView里面第一个item中的TextView

实验结果是:
在onCreate去findView的时候,获取的是LinearLayout里面的TextView。但是我postDelay在去find一遍的时候,获取到的就是ListView里面的TextView了。

View.findViewById是深度优先的

下图所示:fuck是LinearLayout里面的TextView,shit是ListView中item的TextView

View.findViewById是深度优先的

显然,onCreate的时候,Listview尚未被item填充,因此它的children实际上是空的,因此没法进行深度的遍历,找不到任何东西,当ListView已经被填充了,那么findViewById以深度遍历的形式去遍历,那么就会优先找到里面的元素。

因此,在给自定义布局加id的时候,最好还是在前面加上一个命名空间,以止不知何时的findViewById获取到错误的View导致bug

脚本宝典总结

以上是脚本宝典为你收集整理的View.findViewById是深度优先的全部内容,希望文章能够帮你解决View.findViewById是深度优先的所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。