美文网首页
Android findViewById()执行流程

Android findViewById()执行流程

作者: 折剑游侠 | 来源:发表于2020-05-20 11:09 被阅读0次

    虽然现在都不手写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。

    相关文章

      网友评论

          本文标题:Android findViewById()执行流程

          本文链接:https://www.haomeiwen.com/subject/twkgohtx.html