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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章