源码版本:Android 10
将布局文件id通过findViewById方法传递给父类AppCompatActivity,此处源码如下: @Override
public <T extends View> T findViewById(@IdRes int id) {
return getDelegate().findViewById(id);
}
关于getDelegate方法在此处就不在介绍,可以去看setContentView源码解读。最终调用的还是AppCompatDelegateImpl中的findViewById方法,该方法源码如下:
@Nullable
@Override
public <T extends View> T findViewById(@IdRes int id) {
ensureSubDecor();
//mWindow是PhoneWindow的实例对象
return (T) mWindow.findViewById(id);
}
mWindow.findViewById(id)最终调用的是Window的findViewById方法,该方法源代码如下:
@Nullable
public <T extends View> T findViewById(@IdRes int id) {
//getDecorView()将会返回mDecor,它是DecorView(继承至FrameLayout)的实例
return getDecorView().findViewById(id);
}
上述findViewById最终调用的是View的findViewById,该方法的源代码如下所示:
public final <T extends View> T findViewById(@IdRes int id) {
if (id == NO_ID) {
return null;
}
return findViewTraversal(id);
}
View的findViewTraversal方法的源码如下所示:
protected <T extends View> T findViewTraversal(@IdRes int id) {
if (id == mID) { //mID在View被创建传来时就已经赋值了
return (T) this;
}
return null;
}
DecorView继承关系如下所示:
@Override
protected <T extends View> T findViewTraversal(@IdRes int id) {
if (id == mID) {
return (T) 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) {
//递归调用通过id寻找控件
v = v.findViewById(id);
if (v != null) {
return (T) v;
}
}
}
return null;
}