Process Analysis of loading Android view to window, android View
In the previous blog, the Handler principle in Android talked about Handler and talked about how android Activity started to execute the onCreate method. This article mainly starts from the setContentView method which must be written in the onCreate method, study how the Layout View is loaded to the mobile phone window.
When setContentView is executed
public void setContentView(int layoutResID) { getWindow().setContentView(layoutResID); initActionBar();}
It can be seen that it is actually the setContentView method of the Window class.
private Window mWindow;public Window getWindow() { return mWindow;}
The Window class is an abstract class. The following describes its implementation class. MWindow is initialized in
final void attach(……) { …… mWindow = PolicyManager.makeNewWindow(this); mWindow.setCallback(this); mWindow.getLayoutInflater().setPrivateFactory(this);…… }
The Attach method is in the main method. For more information, see the previous blog. The static method of the PolicyManager class is called. makeNewWindow is used to generate a Window object.
private static final String POLICY_IMPL_CLASS_NAME = "com.android.internal.policy.impl.Policy";private static final IPolicy sPolicy;static { try { Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME); sPolicy = (IPolicy)policyClass.newInstance(); }…… }public static Window makeNewWindow(Context context) { return sPolicy.makeNewWindow(context);}
We can see that the Window object is obtained through the makeNewWindow method of the Policy class. Here is an instance of the Policy obtained through the reflection mechanism.
public Window makeNewWindow(Context context) { return new PhoneWindow(context);}
We can see that it is actually a PhoneWindow. According to polymorphism, PhoneWindow # setContentWindow is actually called above.
Public void setContentView (int layoutResID) {if (mContentParent = null) {installDecor (); // 1} else {mContentParent. removeAllViews ();} mLayoutInflater. inflate (layoutResID, mContentParent); // 2 fill the layoutResID. Its Parent View is mContentParent, which is in the installDecor method. mContentParent = generateLayout (mDecor ); final Callback cb = getCallback (); if (cb! = Null &&! IsDestroyed () {cb. onContentChanged ();}}
Execute to installDecor ()
Private void installDecor () {if (mDecor = null) {mDecor = generateDecor (); // generates a decoration window that inherits from FrameLayout mDecor. setDescendantFocusability (ViewGroup. FOCUS_AFTER_DESCENDANTS); mDecor. setIsRootNamespace (true); if (! MInvalidatePanelMenuPosted & mInvalidatePanelMenuFeatures! = 0) {mDecor. postOnAnimation (mInvalidatePanelMenuRunnable) ;}}if (mContentParent = null) {mContentParent = generateLayout (mDecor); // generates a layout and returns the parent layout, check the mDecor code. makeOptionalFitsSystemWindows (); mTitleView = (TextView) findViewById (com. android. internal. r. id. title );......}}}
The generateLayout code is as follows:
Protected ViewGroup generateLayout (DecorView decor) {// Apply data from current theme. typedArray a = getWindowStyle (); // obtain the currently set topic ...... if (. getBoolean (com. android. internal. r. styleable. window_windowNoTitle, false) {requestFeature (FEATURE_NO_TITLE); // you can see that the windows configured in AndroidManifest are actually modified here in the Code} else if (. getBoolean (com. android. internal. r. styleable. window_windowActionBar, false) {// Don't Llow an action bar if there is no title. requestFeature (FEATURE_ACTION_BAR);} if (. getBoolean (com. android. internal. r. styleable. window_windowActionBarOverlay, false) {requestFeature (FEATURE_ACTION_BAR_OVERLAY );}...... // lines 19-63 get the corresponding default Layout Based on the specified window style, such as whether there is a title or not. // These la s are displayed in D: \ SoftWare \ Java \ android4.2-source \ frameworks \ base \ core \ res \ layout int layoutResource; int features = getLocalFeatures (); if (featu Res & (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;} removeFeature (FEATURE_ACTION_BAR);} else if (features & (1 <FEATURE_PROGRESS) | (1 <FEATURE_INDETERMINATE_PROGR ESS )))! = 0 & (features & (1 <FEATURE_ACTION_BAR) = 0) {layoutResource = com. android. internal. r. layout. screen_progress;} else if (features & (1 <FEATURE_CUSTOM_TITLE ))! = 0) {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;} removeFeature (FEATURE_ACTION_BAR);} else if (features & (1 <FEATURE_NO_TITLE) = 0) {if (mIsFloating) {TypedV Alue 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) {if (features & (1 <FEATURE_ACTION_BAR_OVERLAY ))! = 0) {layoutResource = com. android. internal. r. layout. screen_action_bar_overlay;} else {layoutResource = com. android. internal. r. layout. screen_action_bar;} else {layoutResource = com. android. internal. r. layout. screen_title ;}} else if (features & (1 <FEATURE_ACTION_MODE_OVERLAY ))! = 0) {layoutResource = com. android. internal. r. layout. screen_simple_overlay_action_mode;} else {layoutResource = com. android. internal. r. layout. screen_simple;} mDecor. startChanging (); View in = mLayoutInflater. inflate (layoutResource, null); // fill the layoutResource selected based on the above judgment into View decor. addView (in, new ViewGroup. layoutParams (MATCH_PARENT, MATCH_PARENT); // call the addView method of the decoration window to add the View generated in the previous step to the ViewGroup contentParent = (ViewGroup) findViewById (ID_ANDROID_CONTENT) of the decoration window ); // ID_ANDROID_CONTENT corresponds to @ android: id/content is actually a FrameLayout ...... mDecor. finishChanging (); return contentParent ;}
The following are the most commonly used layoutResource layout files in the folder D: \ SoftWare \ Java \ android4.2-source \ frameworks \ base \ core \ res \ layout.
Screen-title.xml
<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:layout_width="match_parent" android:layout_height="?android:attr/windowTitleSize" style="?android:attr/windowTitleBackgroundStyle"> <TextView android:id="@android:id/title" style="?android:attr/windowTitleStyle" android:background="@null" android:fadingEdge="horizontal" android:gravity="center_vertical" android:layout_width="match_parent" android:layout_height="match_parent" /> </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 outermost layer is a linear layout, including the frame layout (including a TextView is actually the title) and the frame layout. In fact, this is the most common form. The default program is like this.
Screen-simple.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:orientation="vertical"> <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/content" android:layout_width="match_parent" android:layout_height="match_parent" android:foregroundInsidePadding="false" android:foregroundGravity="fill_horizontal|top" android:foreground="?android:attr/windowContentOverlay" /></LinearLayout>
Obviously, this is the layout loaded by default during full screen setting.
We can see that FrameLayout with the id of content exists, because it needs to load the xml
According to the Screen-title.xml as an example, roughly like this
Through the above analysis, we understand the following points:
1. The interface presented by the Activity is actually managed by a PhoneWindow class. A DecorView Member in this class is a container at the outermost layer.
2. The figure above is very important and shows the window structure.
3. What is Activity? It's hard to say clearly... ^_^ In short, it is different from the first understanding.
4. Check the source code if you have any questions. Code is the best teacher!