【问题标题】:How does findViewById initialise a viewfindViewById 如何初始化视图
【发布时间】:2013-02-10 18:22:14
【问题描述】:

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

考虑一下:

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

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

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

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

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

[编辑]

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

【问题讨论】:

  • +5 for the queston....因为你的问题我已经研究并找到了有关基本流程的完整信息....感谢@Leonidos

标签: android


【解决方案1】:

findViewById 什么都不做。它只是查看视图层次结构并返回对请求viewId 的视图的引用。 View 已创建并存在。如果您不致电 findViewById 获取某些视图,则没有任何变化。

观看次数被LayoutInflator 夸大。当您调用setContentView 时,会解析xml 布局并创建视图层次结构。

LayoutInflater 传递给 Button 的构造函数的属性。检查LayoutInflator source code

【讨论】:

  • 啊,我明白了。您的意思是在视图层次结构中,引用的视图已经通过调用正确后代类的 ctor 来实例化?
  • 属性通过布局充气器传递给 Button 的构造函数。检查LayoutInflarot source code
【解决方案2】:

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

来自Android源码:

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;
}

【讨论】:

  • 什么是mId,当我在视图类中搜索时,mId被分配给No_ID..它在哪里将mId分配给遍历的View id
  • @Pragnani mId 是视图的分配 ID。当您/inflater 在视图上调用 setId(int id) 时,mID 被设置为提供的 int 值。
猜你喜欢
  • 2014-08-22
  • 2016-11-23
  • 2018-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-10
  • 1970-01-01
相关资源
最近更新 更多