Android findViewById()執行流程

雖然現在都不手寫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。

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