findViewById的工作原理

findViewById的工作原理

那么findViewById是怎么工作的了? 我们沿着继承树向上找. 
1.Activity中

 public View findViewById(int id) {
    return getWindow().findViewById(id);
}

2.getWindow:

public Window getWindow() {
    return mWindow;
}

mWindow 是 private Window mWindow; 是一个Window类型的变量

3.进入Window类,在Window中查找findViewById:

 public View findViewById(int id) {
    return getDecorView().findViewById(id);
}

4.发现getDecorView()是Window中的一个抽象方法。而Window唯一的子类是PhoneWindow.

5.在PhoneWindow找到getDecorView()方法

public final View getDecorView() {
    if (mDecor == null) {
        installDecor();
    }
    return mDecor;
} 

而mDecor是Phone的一个内部类DecorView

private final class DecorView extends FrameLayout implements RootViewSurfaceTaker 

它继承了FrameLayout ,而FrameLayout 是ViewGroup的子类

6.最终我们在ViewGroup中找到了执行findViewById真正的主体方法。

@Overrideprotected 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 & PFLAG_IS_ROOT_NAMESPACE) == 0) {
            v = v.findViewById(id);

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

    return null;
}

该方法意思就是遍历我们前面已经加载好的View数组对每个view执行findViewById 
,这个findViewById是在View中被实现的。它会调用findViewTraversal来辨别寻找的id与找到的id是否相等

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

而这个mID的值是在View被初始化时就已经被赋值了。通过遍历如果id存在,就能成功找到View

发布了105 篇原创文章 · 获赞 56 · 访问量 22万+

猜你喜欢

转载自blog.csdn.net/suwenlai/article/details/105168387