Analysis of Android View system from setContentView (1)

Source: Internet
Author: User

Analysis of Android View system from setContentView (1)

Today is the Mid-Autumn Festival. I wish you a happy Mid-Autumn Festival. As a person in Beijing, the biggest feeling for the holiday is the lack of atmosphere ~ Mid-Autumn Festival is a particularly important holiday. When I was a child, I had a very happy time in Mid-autumn Festival. I had to eat moon cakes and visit my family during the Mid-Autumn Festival. Now, it is just a holiday for us. We watch TV, books, and good meals at home. Although we have a good life, we have nothing to do with it. Let's get started with today's learning.

Hello World

For those who study programming, the first project of most people is the famous "Hello World". Since K & R set this precedent, there are few people behind it. The same is true for learning Android development. When we create an application for the first time, it is estimated that the program is running, and then output a Hello World on the simulator, we can see that the content in the simplest Activity is roughly like this:

public class MainActivity extends Activity {@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main_activity);}}
Main_activity.xml is roughly like this:

     
  
 
Then execute the program and we can see the Hello World in the simulator.


Figure 1

We do very little in the whole process. In our main_activity.xml, we only have one TextView that displays the text, but we have another title in it. We are curious about how the whole process works? For large systems, the details are always complex and limited at the lower level. So today we only need to look at its basic context.

SetContentView

In general, the content view of the page is set through the setContentView method, so we will take the 2.3 source code as an example to see what setContentView in the Activity has done.

    /**     * Set the activity content from a layout resource.  The resource will be     * inflated, adding all top-level views to the activity.     *      * @param layoutResID Resource ID to be inflated.     */    public void setContentView(int layoutResID) {        getWindow().setContentView(layoutResID);    }         public Window getWindow() {        return mWindow;    }    private Window mWindow;

We can see that the setContentView method of mWindow is actually called. In the Android Touch event distribution process, we have pointed out that the implementation class of Window is the PhoneWindow class, let's move to the setConentView of PhoneWindow. The core source code is as follows:

@ Override public void setContentView (int layoutResID) {if (mContentParent = null) {installDecor (); // 1. Generate DecorView} else {mContentParent. removeAllViews ();} mLayoutInflater. inflate (layoutResID, mContentParent); // 2. Add layoutResId layout to final Callback cb = getCallback (); if (cb! = Null) {cb. onContentChanged () ;}}// construct the mDecor object, and initialize the title bar and Content Parent (the Content area we want to display) private void installDecor () {if (mDecor = null) {mDecor = generateDecor (); // 3. Construct DecorView mDecor. setDescendantFocusability (ViewGroup. FOCUS_AFTER_DESCENDANTS); mDecor. setIsRootNamespace (true);} if (mContentParent = null) {mContentParent = generateLayout (mDecor); // 4. Get the ContentView container, that is, the region where the content is displayed, mTitleView = (TextView) findViewById (com. android. internal. R. id. title); 5. Set 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) ;}}} protected DecorView generateDecor () {return new DecorView (getContext (),-1); // construct an mDecor object}
We can see that the basic process of setContentView is simply summarized as follows:

1. Construct an mDecor object. MDecor is the top-level View of the entire window. It mainly contains the Title and Content View areas (refer to the two areas in Figure 1). The Title area is our Title bar, the Content View area is the area in the xml layout. For more information about mDecor objects, see the Android Touch event distribution process;

2. Set window properties to initialize the title bar area and content display area;

The more complicated here is the generateLayout (mDecor) function. Let's take a look at it.

// Return the ViewGroup container protected ViewGroup generateLayout (DecorView decor) {// Apply data from current theme. // 1. Obtain the Style attribute 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]) + "=" +. GetString (I);} System. out. println (s);} // whether the window is floating mIsFloating =. getBoolean (com. android. internal. r. styleable. window_appswisfloating, false); int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR )&(~ GetForcedWindowFlags (); if (mIsFloating) {setLayout (WRAP_CONTENT, WRAP_CONTENT); setFlags (0, flagsToUpdate);} else {setFlags (updated | updated, flagsToUpdate );} // set whether the title area if (. getBoolean (com. android. internal. r. styleable. window_windowNoTitle, false) {requestFeature (FEATURE_NO_TITLE);} // sets the full-screen flag if (. getBoolean (com. android. internal. r. styleable. window_w IndowFullscreen, false) {setFlags (FLAG_FULLSCREEN, FLAG_FULLSCREEN &(~ GetForcedWindowFlags ();} if (a. getBoolean (com. android. internal. R. styleable. Window_windowShowWallpaper, false) {setFlags (FLAG_SHOW_WALLPAPER, FLAG_SHOW_WALLPAPER &(~ GetForcedWindowFlags ();} WindowManager. LayoutParams params = getAttributes (); // set the input method mode if (! HasSoftInputMode () {params. softInputMode =. getInt (com. android. internal. r. styleable. window_windowSoftInputMode, params. softInputMode);} if (. getBoolean (com. android. internal. r. styleable. window_backgroundDimEnabled, mIsFloating) {/* All dialogs shocould have the window dimmed */if (getForcedWindowFlags () & WindowManager. layoutParams. FLAG_DIM_BEHIND) = 0) {params. flags | = WindowManager. layoutP Arams. FLAG_DIM_BEHIND;} params. dimAmount =. getFloat (android. r. styleable. window_backgroundDimAmount, 0.5f);} // if (params. windowAnimations = 0) {params. windowAnimations =. 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 (getContaine R () = null) {if (mBackgroundDrawable = null) {if (mBackgroundResource = 0) {mBackgroundResource =. getResourceId (com. android. internal. r. styleable. window_windowBackground, 0);} if (mFrameResource = 0) {mFrameResource =. getResourceId (com. android. internal. r. styleable. window_windowFrame, 0);} if (false) {System. out. println ("Background:" + Integer. toHexString (mBackgroundResource) + "Fr Ame: "+ Integer. toHexString (mFrameResource);} mTextColor =. getColor (com. android. internal. r. styleable. window_textColor, 0xFF000000);} // Inflate the window decor. // 2. Select different top-level view la s based on some attributes. For example, if the FEATURE_NO_TITLE attribute is set, select a layout without the Title area; // layoutResource layout is the layout of the entire Activity, which contains the title area and content area. The content area is used to display the content area that I set through // setContentView, that is, the view we want to display. 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 t He 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 (); // 3. Load the View in = mLayoutInflater. inflate (layoutResource, null); // 4. Add the content of layoutResource to mDecor. addView (in, new ViewGroup. layoutParams (MATCH_PARENT, MATCH_PARENT); // 5. Obtain the display area of our content. This is a ViewGroup type and is actually FrameLayout ViewGroup contentParent = (ViewGroup) findViewById (ID_ANDROID_CONTENT ); if (contentParent = null) {throw new RuntimeException ("Window couldn't f Ind content container view ");} if (features & (1 <FEATURE_INDETERMINATE_PROGRESS ))! = 0) {ProgressBar progress = getCircularProgressBar (false); if (progress! = Null) {progress. setIndeterminate (true) ;}/// 6. Set attributes such as background and title. // 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 (mTitleColZ cursor? Http://www.bkjia.com/kf/ware/vc/ "target =" _ blank "class =" keylink "> Principal + PHA + MaGiu/Principal/rXIo7vV4sDvztLDx7 + Principal + 7rPtcS2pbLjsry + Principal + PHByZSBjbGFzcz0 =" brush: java; ">
 
     
      
      
  <FrameLayout android: layout_width = "match_parent" android: layout_height = "? Android: attr/windowTitleSize "style = "? Android: attr/windowTitleBackgroundStyle ">
  </FrameLayout>
  <FrameLayout android: id = "@ android: id/content" android: layout_width = "match_parent" android: layout_height = "0dip" android: layout_weight = "1" android: foregroundGravity = "fill_horizontal | top" android: foreground = "? Android: attr/windowContentOverlay "/>
 

We can see that there are two areas: the title area and the content area. In the generateLayout function

// 5. Obtain the display area of our content. This is a ViewGroup type. In fact, it is FrameLayout ViewGroup contentParent = (ViewGroup) findViewById (ID_ANDROID_CONTENT );

Get the FrameLayout with the content id in xml. This content is the display area of our content. The effect of the entire layout is as follows:


The two regions constitute the mDecor view. Our main_activity.xml is placed in the content view area.

3. Load the top-level layout file, convert it to View, and add it to mDecor;

4. Get the Content container Content Parent, that is, the area used to display our Content;

5. Set Some background images and titles.

After these steps, we get the mContentParent, which is the ViewGroup used to load our views. Let's look back at the setContentView function:

Public void setContentView (int layoutResID) {if (mContentParent = null) {installDecor (); // 1. Generate DecorView, in addition, the top-level view layout is loaded Based on window properties, mContentParent is obtained, and basic attributes are set.} else {mContentParent. removeAllViews ();} mLayoutInflater. inflate (layoutResID, mContentParent); // 2. Load layoutResId to mContentParent. Here layoutResId is our main_activity.xml final Callback cb = getCallback (); if (cb! = Null) {cb. onContentChanged ();}}
Let's take a look at the inflate function of LayoutInflater:

    /**     * Inflate a new view hierarchy from the specified xml resource. Throws     * {@link InflateException} if there is an error.     *      * @param resource ID for an XML layout resource to load (e.g.,     *        R.layout.main_page)     * @param root Optional view to be the parent of the generated hierarchy.     * @return The root View of the inflated hierarchy. If root was supplied,     *         this is the root View; otherwise it is the root of the inflated     *         XML file.     */    public View inflate(int resource, ViewGroup root) {        return inflate(resource, root, root != null);    }    /**     * Inflate a new view hierarchy from the specified xml resource. Throws     * {@link InflateException} if there is an error.     *      * @param resource ID for an XML layout resource to load (e.g.,     *        R.layout.main_page)     * @param root Optional view to be the parent of the generated hierarchy (if     *        attachToRoot is true), or else simply an object that     *        provides a set of LayoutParams values for root of the returned     *        hierarchy (if attachToRoot is false.)     * @param attachToRoot Whether the inflated hierarchy should be attached to     *        the root parameter? If false, root is only used to create the     *        correct subclass of LayoutParams for the root view in the XML.     * @return The root View of the inflated hierarchy. If root was supplied and     *         attachToRoot is true, this is root; otherwise it is the root of     *         the inflated XML file.     */    public View inflate(int resource, ViewGroup root, boolean attachToRoot) {        if (DEBUG) System.out.println("INFLATING from resource: " + resource);        XmlResourceParser parser = getContext().getResources().getLayout(resource);        try {            return inflate(parser, root, attachToRoot);        } finally {            parser.close();        }    }
In fact, the layoutResId Layout View is appended to the mContentParent. DecorView

Step: DecorView.

ViewGroup

In terms of semantics, ViewGroup is a View group. It also inherits from the View class, which is actually a View container. Let's look at the official definition:

 * A ViewGroup is a special view that can contain other views * (called children.) The view group is the base class for layouts and views * containers. This class also defines the * {@link android.view.ViewGroup.LayoutParams} class which serves as the base * class for layouts parameters.
We use ViewGroup to organize and manage subviews. For example, common ViewGroup types such as FrameLayout, LinearLayout, RelativeLayout, and ListView are ViewGroup. Use ViewGroup to build a view tree.



View

View is a visible component on the UI interface. Any component visible on the UI is a subclass of View. See the official definition:

 * This class represents the basic building block for user interface components. A View * occupies a rectangular area on the screen and is responsible for drawing and * event handling. View is the base class for widgets, which are * used to create interactive UI components (buttons, text fields, etc.). The * {@link android.view.ViewGroup} subclass is the base class for layouts, which * are invisible containers that hold other Views (or other ViewGroups) and define * their layout properties.

TextView, Button, ImageView, FrameLayout, LinearLayout, and ListView are all child classes of View.

Summary


The entire window consists of the Title area and Content area. The Content area is the area where we want to display the Content. In this area, mContentParent is the root ViewGroup, which organizes and manages its subviews by mContentParent, to build the entire view tree. When the Activity is started, the content will be displayed on the mobile phone.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.