Android 四大组件之——Acitivity(四) Activity是如何加载显示内容的?

1. 在Activity调用onCreate()等生命周期之前,Activity会调用attach()方法,而在attach()方法中会调用如下代码

onAttach()
{
   PolicyManager.makeNewWindow(this)
}
而makeNewWindow实际上时创建 Window的子类PhoneWindow,也就是说在调用onCreate()方法之前, Activity会首先创建一个PhoneWindow,用于管理显示内容的容器


2.创建了窗体之后,Activity调用onCreate()方法,以下是我们司空见惯的代码

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

}


3.在Activity的setContentview()方法里,会调用如下PhoneWindow的setContentview()

public void setContentView(View view,ViewGroup.LayoutParams params)
{
  getWindow().setContentview(view,params);
}
   getWindow() 实际上返回的是刚开始创建的PhoneWinow


4.执行PhoneWindow  的setContentView()

@Override  
    public void setContentView(int layoutResID) {  
        if (mContentParent == null) {  
            installDecor();      //如果mContentParent为null,则创建容器
        } else {  
            mContentParent.removeAllViews(); //如果不为空,则清除容器上所有内容
        }  
        mLayoutInflater.inflate(layoutResID, mContentParent); //然后在容器上填充布局内容 
        final Callback cb = getCallback();  
        if (cb != null) {  
            cb.onContentChanged();  
        }  
    }  
   installDecor(),究竟创建了一个什么样的容器呢?
    
 private void installDecor() {  
        if (mDecor == null) {  
            mDecor = generateDecor();  
            mDecor.setIsRootNamespace(true);  
        }  
        if (mContentParent == null) {  
            mContentParent = generateLayout(mDecor);  
  
            mTitleView = (TextView)findViewById(com.android.internal.R.id.title);  
            if (mTitleView != null) {  
                if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {  
                    View titleContainer = findViewById(com.android.internal.R.id.title_container);  
                    if (titleContainer != null) {  
                        titleContainer.setVisibility(View.GONE);  
                    } else {  
                        mTitleView.setVisibility(View.GONE);  
                    }  
                    if (mContentParent instanceof FrameLayout) {  
                        ((FrameLayout)mContentParent).setForeground(null);  
                    }  
                } else {  
                    mTitleView.setText(mTitle);  
                }  
            }  
        }  
    }  
  
generateLayout(DecorView decor)又会返回什么呢?

 protected ViewGroup generateLayout(DecorView decor) {  
        // Apply data from current theme.  
  
        TypedArray a = getWindowStyle();  
  
        if (false) {  
            System.out.println("From style:");  
            String s = "Attrs:";  
            for (int i = 0; i < com.android.internal.R.styleable.Window.length; i++) {  
                s = s + " " + Integer.toHexString(com.android.internal.R.styleable.Window[i]) + "="  
                        + a.getString(i);  
            }  
            System.out.println(s);  
        }  
  
        mIsFloating = a.getBoolean(com.android.internal.R.styleable.Window_windowIsFloating, false);  
        int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR)  
                & (~getForcedWindowFlags());  
        if (mIsFloating) {  
            setLayout(WRAP_CONTENT, WRAP_CONTENT);  
            setFlags(0, flagsToUpdate);  
        } else {  
            setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);  
        }  
          
        if (a.getBoolean(com.android.internal.R.styleable.Window_windowNoTitle, false)) {  
            requestFeature(FEATURE_NO_TITLE);  
        }  
  
        if (a.getBoolean(com.android.internal.R.styleable.Window_windowFullscreen, false)) {  
            setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN&(~getForcedWindowFlags()));  
        }  
  
        WindowManager.LayoutParams params = getAttributes();  
          
        if (!hasSoftInputMode()) {  
            params.softInputMode = a.getInt(  
                    com.android.internal.R.styleable.Window_windowSoftInputMode,  
                    params.softInputMode);  
        }  
          
        if (a.getBoolean(com.android.internal.R.styleable.Window_backgroundDimEnabled,  
                mIsFloating)) {  
            /* All dialogs should have the window dimmed */  
            if ((getForcedWindowFlags()&WindowManager.LayoutParams.FLAG_DIM_BEHIND) == 0) {  
                params.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;  
            }  
            params.dimAmount = a.getFloat(  
                    android.R.styleable.Window_backgroundDimAmount, 0.5f);  
        }  
  
        if (params.windowAnimations == 0) {  
            params.windowAnimations = a.getResourceId(  
                    com.android.internal.R.styleable.Window_windowAnimationStyle, 0);  
        }  
          
        // The rest are only done if this window is not embedded; otherwise,  
        // the values are inherited from our container.  
        if (getContainer() == null) {  
            if (mBackgroundDrawable == null) {  
                if (mBackgroundResource == 0) {  
                    mBackgroundResource = a.getResourceId(  
                            com.android.internal.R.styleable.Window_windowBackground, 0);  
                }  
                if (mFrameResource == 0) {  
                    mFrameResource = a.getResourceId(com.android.internal.R.styleable.Window_windowFrame, 0);  
                }  
                if (false) {  
                    System.out.println("Background: "  
                            + Integer.toHexString(mBackgroundResource) + " Frame: "  
                            + Integer.toHexString(mFrameResource));  
                }  
            }  
            mTextColor = a.getColor(com.android.internal.R.styleable.Window_textColor, 0xFF000000);  
        }  
  
        // Inflate the window decor.  
  
        int layoutResource;  
        int features = getLocalFeatures();  
        // System.out.println("Features: 0x" + Integer.toHexString(features));  
        if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {  
            if (mIsFloating) {  
                layoutResource = com.android.internal.R.layout.dialog_title_icons;  
            } else {  
                layoutResource = com.android.internal.R.layout.screen_title_icons;  
            }  
            // System.out.println("Title Icons!");  
        } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0) {  
            // Special case for a window with only a progress bar (and title).  
            // XXX Need to have a no-title version of embedded windows.  
            layoutResource = com.android.internal.R.layout.screen_progress;  
            // System.out.println("Progress!");  
        } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {  
            // Special case for a window with a custom title.  
            // If the window is floating, we need a dialog layout  
            if (mIsFloating) {  
                layoutResource = com.android.internal.R.layout.dialog_custom_title;  
            } else {  
                layoutResource = com.android.internal.R.layout.screen_custom_title;  
            }  
        } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {  
            // If no other features and not embedded, only need a title.  
            // If the window is floating, we need a dialog layout  
            if (mIsFloating) {  
                layoutResource = com.android.internal.R.layout.dialog_title;  
            } else {  
                layoutResource = com.android.internal.R.layout.screen_title;  
            }  
            // System.out.println("Title!");  
        } else {  
            // Embedded, so no decoration is needed.  
            layoutResource = com.android.internal.R.layout.screen_simple;  
            // System.out.println("Simple!");  
        }  
  
        mDecor.startChanging();  
  
        View in = mLayoutInflater.inflate(layoutResource, null);  
        decor.addView(in, new ViewGroup.LayoutParams(FILL_PARENT, FILL_PARENT));  
  
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);  
        if (contentParent == null) {  
            throw new RuntimeException("Window couldn't find content container view");  
        }  
  
        if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {  
            ProgressBar progress = getCircularProgressBar(false);  
            if (progress != null) {  
                progress.setIndeterminate(true);  
            }  
        }  
  
        // Remaining setup -- of background and title -- that only applies  
        // to top-level windows.  
        if (getContainer() == null) {  
            Drawable drawable = mBackgroundDrawable;  
            if (mBackgroundResource != 0) {  
                drawable = getContext().getResources().getDrawable(mBackgroundResource);  
            }  
            mDecor.setWindowBackground(drawable);  
            drawable = null;  
            if (mFrameResource != 0) {  
                drawable = getContext().getResources().getDrawable(mFrameResource);  
            }  
            mDecor.setWindowFrame(drawable);  
  
            // System.out.println("Text=" + Integer.toHexString(mTextColor) +  
            // " Sel=" + Integer.toHexString(mTextSelectedColor) +  
            // " Title=" + Integer.toHexString(mTitleColor));  
  
            if (mTitleColor == 0) {  
                mTitleColor = mTextColor;  
            }  
  
            if (mTitle != null) {  
                setTitle(mTitle);  
            }  
            setTitleColor(mTitleColor);  
        }  
  
        mDecor.finishChanging();  
  
        return contentParent;  
    }  
代码比较多,我们抓重点来看,即标记为红色部分,从上面可以看出,最终是以 decor 为容器

最后用一张关系图来总结一下Activity加载显示内容的过程


Android 四大组件之——Acitivity(四) Activity是如何加载显示内容的?_第1张图片






你可能感兴趣的:(Android基础)