美文网首页
Activity中setContentView做了什么

Activity中setContentView做了什么

作者: 慵懒的阳光丶 | 来源:发表于2019-04-10 09:49 被阅读0次
    我们在开发中每创建一个Activity的同时会通过setContentView(R.layout.xxx)来为其添加布局文件,那么这个布局文件是如何加载进来的呢?下面简单结合源码(8.0)进行分析。

    我们默认写的Activity继承的是AppCompatActivity,跟踪我们的Activity到AppCompatActivity中,代码如下:

     @Override
        public void setContentView(@LayoutRes int layoutResID) {
            getDelegate().setContentView(layoutResID);
        }
    

    继续跟踪setContentView(layoutResID),会进入到AppCompatDelegate中,看到注释说明该方法会取代activity中的setContentView()的调用

       /**
         * Should be called instead of {@link Activity#setContentView(int)}}
         */
        public abstract void setContentView(@LayoutRes int resId);
    

    AppCompatDelegate是一个抽象类,那么我们需要找到该方法的真正实现类,继续跟踪,进入到真正的实现类AppCompatDelegateImpl中

    @Override
        public void setContentView(int resId) {
            ensureSubDecor();
            ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content);
            contentParent.removeAllViews();
            LayoutInflater.from(mContext).inflate(resId, contentParent);
            mOriginalWindowCallback.onContentChanged();
        }
    

    首先看一下ensureSubDecor(),此方法是在装载view之前做的一些准备,这里借用一张图方便理解


    图片.png

    方法如下,不做深入研究了,感兴趣的朋友可以点击深入查看

    private void ensureSubDecor() {
            if (!mSubDecorInstalled) {
                mSubDecor = createSubDecor();
    
                // If a title was set before we installed the decor, propagate it now
                CharSequence title = getTitle();
                if (!TextUtils.isEmpty(title)) {
                    if (mDecorContentParent != null) {
                        mDecorContentParent.setWindowTitle(title);
                    } else if (peekSupportActionBar() != null) {
                        peekSupportActionBar().setWindowTitle(title);
                    } else if (mTitleView != null) {
                        mTitleView.setText(title);
                    }
                }
    
                applyFixedSizeWindow();
    
                onSubDecorInstalled(mSubDecor);
    
                mSubDecorInstalled = true;
    
                // Invalidate if the panel menu hasn't been created before this.
                // Panel menu invalidation is deferred avoiding application onCreateOptionsMenu
                // being called in the middle of onCreate or similar.
                // A pending invalidation will typically be resolved before the posted message
                // would run normally in order to satisfy instance state restoration.
                PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
                if (!mIsDestroyed && (st == null || st.menu == null)) {
                    invalidatePanelMenu(FEATURE_SUPPORT_ACTION_BAR);
                }
            }
        }
    

    思路回到AppCompatDelegateImpl中的setContentView,为了不用翻上去看,这里再贴一遍

    @Override
        public void setContentView(int resId) {
            ensureSubDecor();
            ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content);
            contentParent.removeAllViews();
            LayoutInflater.from(mContext).inflate(resId, contentParent);
            mOriginalWindowCallback.onContentChanged();
        }
    

    结合上面DectorView的结构图我们可以很清晰的看到,这里通过
    LayoutInflater.from(mContext).inflate(resId, contentParent)
    将我们传入的布局id转换成view并添加到DecorView中,到此布局文件就转换成view加载到DecorView中了

    相关文章

      网友评论

          本文标题:Activity中setContentView做了什么

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