Android source code parsing: setContentView and setcontentview

Source: Internet
Author: User

Android source code parsing: setContentView and setcontentview

Reprinted please indicate the source: bytes]

During normal development, you are certainly familiar with setContentView, so are you curious about its internal implementation ~~~ I am lucky to finally see some source code of PhoneWindow. Today I will take you back to the source code ~~

1. Activity setContentView

Needless to say, go to the Activity's setContentView

 public void setContentView(int layoutResID) {        getWindow().setContentView(layoutResID);        initActionBar();    }

You can see that the Window is obtained, and then the setContentView of the Window is called.

2. PhoneWindow setContentView

Here, the implementation class of Window is PhoneWindow (package com. android. internal. policy. impl;). Let's look at its implementation:

 @Override    public void setContentView(int layoutResID) {        if (mContentParent == null) {            installDecor();        } else {            mContentParent.removeAllViews();        }        mLayoutInflater.inflate(layoutResID, mContentParent);        final Callback cb = getCallback();        if (cb != null && !isDestroyed()) {            cb.onContentChanged();        }    }

As you can see, first determine whether the mContentParent is null. If yes, call installDecor (). Otherwise, remove all the internal child Views and use LayoutInflater. inflate places the passed layout in mContentParent.

It can be seen from this that mContentParent is a ViewGroup and encapsulates our entire layout file. installDecor () is estimated to initialize our mContentParent and we will verify it later.

Next, we get a CallBack object through getCallBack. In fact, the obtained CallBack is our Activity. You can see that our Activity implements the CallBack interface.

This Callback is obviously a Callback. When PhoneWindow receives the touch, IO, menu, and other related events distributed to it by the system, it can call back the corresponding Activity for processing. As for the methods that Callback can call back, you can check the declaration method of this interface. Of course, this is not our key here, because our setContentView only calls back onContentChanged, while onContentChanged is an empty implementation in the Activity.

Now let's take a look at our installDecor ()

3. PhoneWindow installDecor

Private void installDecor () {if (mDecor = null) {mDecor = generateDecor (); mDecor. setDescendantFocusability (ViewGroup. FOCUS_AFTER_DESCENDANTS); mDecor. setIsRootNamespace (true );//...}} if (mContentParent = null) {mContentParent = generateLayout (mDecor); mTitleView = (TextView) findViewById (com. android. internal. r. id. title); if (mTitleView! = Null) {// hide Based on FEATURE_NO_TITLE, or set the value of mTitleView //...} else {mActionBar = (ActionBarView) findViewById (com. android. internal. r. id. action_bar); if (mActionBar! = Null) {// set the title and icon of the ActionBar. initialize the display of the Actionbar according to the FEATURE //...}}}}

The code here is relatively long and some code for initializing Actionbar styles is deleted.

We can see that not only mContentParent is initialized here, but also generateDecor () is called before; An mDecor is initialized. mDecor is a DecorView object and is a subclass of FrameLayout.

After mDecor is obtained, set the focus acquisition method to acquire it only when its children and grandchildren do not need it.

Then, use generateLayout (mDecor); pass mDecor as a parameter, and then get our mContentParent;

Next, we start to get the control through findViewById, And the findViewById code here is as follows:

 public View findViewById(int id) {        return getDecorView().findViewById(id);    }

GetDecorView returns our mDecor.

Here we guess, first initialize mDecor, then initialize mContentParent through mDecor, then mDecor can use findViewById method. So I think the mDecor Initialization Method

In generateDecor (), we must have placed a layout or control for our mDecor (the simplest is to press the layout file into inflate), and mContentParent may be a subview in mDecor.

Is that true?

Let's take a look at the implementation of the generateDecor () method:

4. PhoneWindow generateDecor

protected DecorView generateDecor() {        return new DecorView(getContext(), -1);    }
  public DecorView(Context context, int featureId) {            super(context);            mFeatureId = featureId;        }

Unfortunately, our generateDecor () only initializes a FrameLayout object and does not push the layout file in it. It seems that we have some questions. But it's okay, since this method does not exist, the layout file must be set in generateLayout (mDecor);, and the name is similar to this.

5. PhoneWindow generateLayout

Protected ViewGroup generateLayout (DecorView decor) {// Apply data from current theme. typedArray a = getWindowStyle ();//... window_windowIsFloating, Window_windowNoTitle, Window_windowActionBar... // first, perform requestFeature or setFlags if (. getBoolean (com. android. internal. r. styleable. window_windowNoTitle, false) {requestFeature (FEATURE_NO_TITLE );}//... if (. getBoolean (com. Android. internal. R. styleable. Window_windowFullscreen, false) {setFlags (FLAG_FULLSCREEN, FLAG_FULLSCREEN &(~ GetForcedWindowFlags ()));}//... determine whether menukey WindowManager is required based on the current sdk version. layoutParams params = getAttributes (); // set params through the attributes set in. softInputMode: the keyboard mode. // if the current Activity is a floating Activity, set FLAG_DIM_BEHIND in params and record the dimAmount value. // And in params. windowAnimations record WindowAnimationStyle // 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) {TypedValue res = new TypedValue (); getContext (). getTheme (). resolveAttribute (com. android. internal. r. attr. dialogTitleIconsDecorLayout, res, true); layoutResource = res. resourceId;} else {layoutResource = com. android. internal. r. layout. screen_title_icons;} // XXX Remove this once action bar supports these features. removeFeature (FEATURE_ACTION_BAR); // System. out. println (" Title Icons! ");} Else if (features & (1 <FEATURE_PROGRESS) | (1 <FEATURE_INDETERMINATE_PROGRESS )))! = 0 & (features & (1 <FEATURE_ACTION_BAR) = 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) {TypedValue res = new TypedValue (); getContext (). getTheme (). resolveAttribute (com. android. internal. r. attr. dialogCustomTitleDecorLayout, res, true); layoutResource = res. resourceId;} else {layoutResource = com. android. internal. r. layout. screen_custom_title;} // XXX Remov E this once action bar supports these features. removeFeature (FEATURE_ACTION_BAR);} 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) {TypedValue res = new TypedValue (); getContext (). getTheme (). resolveAttribute (com. android. internal. r. attr. dialogTitleDecorLayout, Res, true); layoutResource = res. resourceId;} else if (features & (1 <FEATURE_ACTION_BAR ))! = 0) {layoutResource = com. android. internal. r. layout. screen_action_bar;} else {layoutResource = com. android. internal. r. layout. screen_title;} // System. out. println ("Title! ");} Else if (features & (1 <FEATURE_ACTION_MODE_OVERLAY ))! = 0) {layoutResource = com. android. internal. r. layout. screen_simple_overlay_action_mode;} else {// Embedded, so no decoration is needed. layoutResource = com. android. internal. r. layout. screen_simple; // System. out. println ("Simple! ");} View in = mLayoutInflater. inflate (layoutResource, null); decor. addView (in, new ViewGroup. layoutParams (MATCH_PARENT, MATCH_PARENT); ViewGroup contentParent = (ViewGroup) findViewById (ID_ANDROID_CONTENT );//... return contentParent ;}}

The Code is also relatively long. First, getWindowStyle obtains the properties defined in our Window in the theme of the current Window. For details, refer to \ frameworks \ base \ core \ res \ values \ attrs. xml.

 <!-- The set of attributes that describe a Windows's theme. -->    <declare-styleable name="Window">        <attr name="windowBackground" />        <attr name="windowContentOverlay" />        <attr name="windowFrame" />        <attr name="windowNoTitle" />        <attr name="windowFullscreen" />        <attr name="windowOverscan" />        <attr name="windowIsFloating" />        <attr name="windowIsTranslucent" />        <attr name="windowShowWallpaper" />        <attr name="windowAnimationStyle" />        <attr name="windowSoftInputMode" />        <attr name="windowDisablePreview" />        <attr name="windowNoDisplay" />        <attr name="textColor" />        <attr name="backgroundDimEnabled" />        <attr name="backgroundDimAmount" />
Then, based on the values of these attributes, we can perform various requestFeature and setFlags operations on our windows. So here is the resolution where we set theme for the Activity. theme can be set in AndroidManifest.

Next we will go to the key part, line 21-75: assign a value to layoutResource by judging features and mIsFloating. The value can be R. layout. screen_custom_title; R. layout. screen_action_bar; and so on. As for features, in addition to those set in theme, we can also perform requestFeature before setContentView in onCreate of Activity. It also explains why we need to call requestFeature before setContentView to set full screen or something.

After the layoutResource is obtained, line 78 converts the layout into a view through LayoutInflater and adds it to our decor, that is, the input mDecor.

The following 81 rows: Through mDecor. input findViewById to R. id. content (I believe this id has been heard more or less), returns the View with the id of content in the mDecor (layout), which is generally FrameLayout.

Now, we can see that our mDecor is a FrameLayout. Then we will select the layout file in the System Based on theme, convert the layout file to view through inflate, and add it to mDecor; these layout files contain a FrameLayout with the content id and return it to mContentParent.

After the value of our mContentParent has been set, do you remember what we did? Paste the setContentView of PhoneWindow again

  @Override    public void setContentView(int layoutResID) {        if (mContentParent == null) {            installDecor();        } else {            mContentParent.removeAllViews();        }        mLayoutInflater.inflate(layoutResID, mContentParent);        final Callback cb = getCallback();        if (cb != null && !isDestroyed()) {            cb.onContentChanged();        }    }

With mContentParent, add the layout file we wrote to mContentParent through inflater.


You can view R. layout. xxx in frameworks \ base \ core \ res \ layout.

Example: R. layout. screen_custom_title.xml

<?xml version="1.0" encoding="utf-8"?><!--This is a custom layout for a screen.--><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:fitsSystemWindows="true">    <!-- Popout bar for action modes -->    <ViewStub android:id="@+id/action_mode_bar_stub"              android:inflatedId="@+id/action_mode_bar"              android:layout="@layout/action_mode_bar"              android:layout_width="match_parent"              android:layout_height="wrap_content" />    <FrameLayout android:id="@android:id/title_container"         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" /></LinearLayout>
The above title_container is used to hold the custom Title container, and the following content is the container for storing the layout we set. For examples of custom titles, refer to Baidu.


At this point, our setContentView analysis is complete. Let's review it:

Initialize mDecor, that is, DecorView is a subclass of FrameLayout. The Root View of the entire window.

Then, select the appropriate layout based on the value of theme and put it into our mDecor through infalter. inflater.

These la s generally contain ActionBar, Title, and FrameLayout with the id of content.

Finally, the layout we set in the Activity will be pushed to the FrameLayout with the content id through infalter. inflater.



Bytes ----------------------------------------------------------------------------------------------------------

Some of the bloggers have already been online. If you do not like boring text, stamp it (for initial record, we look forward to your support ):

1. Android custom controls create Android streaming layout and popular labels

2. Implementation of Android intelligent robot xiaomu

3. High imitation QQ5.0 slide

4. High imitation 5.2.1 main interface and message reminder








Related Article

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.