虽然现在都不手写findViewById,但还是有必要看一下源码流程。
val tv = findViewById<TextView>(R.id.tv)
AppCompatActivity.findViewById()
public <T extends View> T findViewById(@IdRes int id) {
return getDelegate().findViewById(id);
}
getDelegate()返回AppCompatActivity代理类实例AppCompatDelegateImpl
AppCompatDelegateImpl.findViewById()
public <T extends View> T findViewById(@IdRes int id) {
ensureSubDecor();
return (T) mWindow.findViewById(id);
}
Window.findViewById()
public <T extends View> T findViewById(@IdRes int id) {
return getDecorView().findViewById(id);
}
Window.getDecorView()是个抽象方法,Window实现类PhoneWindow重写了该方法
PhoneWindow.getDecorView()
private DecorView mDecor;
public final View getDecorView() {
if (mDecor == null || mForceDecorInstall) {
installDecor();
}
return mDecor;
}
DecorView继承自FrameLayout是个ViewGroup
DecorView.findViewById()--->View.findViewById()
public final <T extends View> T findViewById(@IdRes int id) {
if (id == NO_ID) {
return null;
}
return findViewTraversal(id);
}
ViewGroup重写了findViewTraversal()方法
ViewGroup.findViewTraversal()
@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) {
v = v.findViewById(id);
if (v != null) {
return (T) v;
}
}
}
return null;
}
遍历调用子View的findViewById(),继续跟进
View.findViewTraversal()
protected <T extends View> T findViewTraversal(@IdRes int id) {
if (id == mID) {
return (T) this;
}
return null;
}
id == mID则返回此View
流程很简单。findViewById()方法从Window开始,调用顶层View>DecorView.findViewById()。DecorView是ViewGroup,遍历调用子View的findViewById(),深度递归,直到找到id相同的View。
网友评论