美文网首页
setcontentview源码简单分析

setcontentview源码简单分析

作者: 愤怒的板蓝根 | 来源:发表于2018-09-20 16:24 被阅读0次

    首先我们先进入 *setContentView 这个方法

      * @param layoutResID Resource ID to be inflated.
      *
     * @see #setContentView(android.view.View)
     * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
     */
    public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }
    public Window getWindow() {
        return mWindow;
    }
     public abstract void setContentView(@LayoutRes int layoutResID);
    

    可以看到这只是一个抽象类 说明我们找的地方找错了 我们应该去找mWindow赋值的地方所以我们来到了attach 这个方法

        final void attach(...) {
        attachBaseContext(context);
    
        mFragments.attachHost(null /*parent*/);
    
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }
        mUiThread = Thread.currentThread();
          ....
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) {
            if (lastNonConfigurationInstances != null) {
                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
            } else {
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            }
        }
    
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;
    
        mWindow.setColorMode(info.colorMode);
    
        setAutofillCompatibilityEnabled(application.isAutofillCompatibilityEnabled());
        enableAutofillCompatibilityIfNeeded();
    }
    

    我们可以从 mWindow = new PhoneWindow(this, window, activityConfigCallback);这句代码中 看出 它New了一个 PhoneWindow 的实例 我们再接着去看下 ,而点开PhoneWindow的源码我们会发现它继承自Window类,由此我们可以知道,PhoneWindow类是Window的具体实现类.
    我们继续看setcontentView()这个方法的实现

     @Override
       public void setContentView(int layoutResID) {
        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing  the window
        // decor, when theme attributes and the like are crystalized. Do not check the feature
        // before this happens.
        if (mContentParent == null) {//当mContentParent为空的时候 也就是没有放置父布局 
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {//有没有使用过度动画,也就是转场动画
            mContentParent.removeAllViews();
        }
    
        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());//利用Scene来过度启动
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);//否则则通过LayoutInflater对象转换为View树,并且添加至mContentParent视图中。
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }
    

    首先他做了一个if (mContentParent == null)判断 我们先来看下这个是啥

    // This is the view in which the window contents are placed. It is either
    // mDecor itself, or a child of mDecor where the contents go.
    ViewGroup mContentParent;  
    

    可以看到他只是一个ViewGroup 结合注释 翻译过来的内容就是(这是放置窗口内容的视图。 它是mDecor本身,或内容的mDecor的子布局。) 我们接着去看installDecor()

    private void installDecor() {
    mForceDecorInstall = false;
    if (mDecor == null) {//判断是否为空
    mDecor = generateDecor(-1);//重新NEW一个Decor 实例 mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
    mDecor.setIsRootNamespace(true);
    if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
    mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
    }
    } else {
    mDecor.setWindow(this);
    }
    //一开始DecorView未加载到mContentParent,所以此时mContentParent=null
    if (mContentParent == null) {
    mContentParent = generateLayout(mDecor);

            // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
            mDecor.makeOptionalFitsSystemWindows();
    
            final DecorContentParent decorContentParent = (DecorContentParent)  mDecor.findViewById(
                    R.id.decor_content_parent);
             ...设置title  转场动画等
            }
    

    我们进入generateLayou 这个方法看下

       protected ViewGroup generateLayout(DecorView decor) {
        // Apply data from current theme.
    。。。    
          if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
            layoutResource = R.layout.screen_simple_overlay_action_mode;
        } else {
            // Embedded, so no decoration is needed.
            layoutResource = R.layout.screen_simple;
            // System.out.println("Simple!");
        }
        mDecor.startChanging();
         //加载资源
            mDecor.startChanging();
        mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
         //加载一个ID_ANDROID_CONTENT 布局
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
        if (contentParent == null) {
            throw new RuntimeException("Window couldn't find content container view");
        }
    
      。。。
        // Remaining setup -- of background and title -- that only applies
        // to top-level windows.
        if (getContainer() == null) {
            final Drawable background;
            if (mBackgroundResource != 0) {
                background = getContext().getDrawable(mBackgroundResource);
            } else {
                background = mBackgroundDrawable;
            }
            mDecor.setWindowBackground(background);
    
            final Drawable frame;
            if (mFrameResource != 0) {
                frame = getContext().getDrawable(mFrameResource);
            } else {
                frame = null;
            }
            mDecor.setWindowFrame(frame);
    
            mDecor.setElevation(mElevation);
            mDecor.setClipToOutline(mClipToOutline);
    
            if (mTitle != null) {
                setTitle(mTitle);
            }
    
            if (mTitleColor == 0) {
                mTitleColor = mTextColor;
            }
            setTitleColor(mTitleColor);
        }
    
        mDecor.finishChanging();
    
        return contentParent;    }

    相关文章

      网友评论

          本文标题:setcontentview源码简单分析

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