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