10

我刚刚为被 findViewById 困惑的人写了一个答案,我意识到我的理解存在差距。这个问题仅用于知识和好奇心。

考虑一下:

button = (Button)findViewById(R.id.button);

findViewById返回 的实例View,然后将其强制转换为目标类。到目前为止一切都很好。

要设置视图,请从关联的 XML 声明中的参数findViewById构造一个AttributeSet,并将其传递给View.

然后我们将View实例转换为Button.

get如何AttributeSet依次传递给Button构造函数?

[编辑]

所以我很困惑:)。重点是当布局膨胀时,视图层次结构已经包含视图后代类的实例。findViewById 只是返回对它的引用。当你想到它时很明显 - doh..

4

2 回答 2

14

findViewById什么也没做。它只是查看视图层次结构并返回对带有 requests 的视图的引用viewIdView已经创建并存在。如果您不要求findViewById某些视图,则没有任何变化。

视图被夸大了LayoutInflator。当您调用setContentViewxml 布局时,将解析并创建视图层次结构。

属性传递给 Button 的构造函数LayoutInflater。检查LayoutInflator 源代码

于 2013-02-10T18:26:53.257 回答
6

我不认为findViewById()构造或实例化视图。它将在已膨胀布局的视图层次结构中搜索具有匹配 id 的视图。此方法对 aView和 a 的工作方式不同ViewGroup

来自安卓源代码:

View.findViewById()如果此视图具有给定的 id 或 null,则返回相同的 View 对象,它调用:

protected View findViewTraversal(int id) {
    if (id == mID) {
        return this;
    }
    return null;
}

ViewGroup.findViewById()遍历子视图并在这些视图上调用相同的方法,它调用:

 protected View findViewTraversal(int id) {
    if (id == mID) {
        return this;
    }

    final View[] where = mChildren;
    final int len = mChildrenCount;

    for (int i = 0; i < len; i++) {
        View v = where[i];

        if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
            v = v.findViewById(id);

            if (v != null) {
                return v;
            }
        }
    }

    return null;
}
于 2013-02-10T18:33:16.107 回答