findViewById如何初始化视图

Sim*_*mon 9 android

我刚刚为findViewById困惑的人写了一个答案,我意识到我的理解上有差距.这个问题只是为了知识和好奇心.

考虑一下:

button = (Button)findViewById(R.id.button);
Run Code Online (Sandbox Code Playgroud)

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

要设置视图,请从相关XML声明中的参数findViewById构造一个AttributeSet它传递给构造函数的参数View.

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

如何将AttributeSetget传递给Button构造函数?

[编辑]

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

Leo*_*dos 13

findViewById什么也没做.它只是查看视图层次结构并返回对请求的视图的引用viewId.View已经创建并存在.如果你没有要求findViewById某些观点没有任何变化.

意见膨胀LayoutInflator.当您调用setContentViewxml时,将解析布局并创建视图层次结构.

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


S.D*_*.D. 6

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

来自Android源代码:

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

protected View findViewTraversal(int id) {
    if (id == mID) {
        return this;
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)