The setContentView flow of the Activity
1. The setContView method in activity.java first calls getWindow(), also known as PhoneWindow
2. GetWindow () method need to find the activity start a process, ActivityThread. PerformLaunchActivity () method
1) Get the Activity object from the meter class reflection
2) Call the Attach method of the activity, which creates a PhoneWindow.
3) Call the callActivityOnCreate method of the meter class.
3.PhoneWindow setContentView method
1) Call the installDecor() method to create a DecorView(frameLayout) and get the ContentParent(ViewGroup, a layout view on XML layout).
- The generateDecor(-1) method creates a DecorView() object
- generateLayout(mDecor)
Get the attribute setting information from the XML and set it to.
Add an XML layout selected by attributes to the DecorView.
Gets the controls on the layout
2) Render.xml onto Content
Second, the layout structure
Third, AppCompatActivity process
1.AppCompatActivity setContentView() calls AppCompatDelegateIml setContentView()
AppCompatActivity.java
AppCompatDelegate.java
AppcompatDelegateIml.java
2. EnsureSubDector () method.
Basically, creatSubDecor () is called.
3. CreatSubDecor () method.
-
Gets the attributes of the XML configuration
-
Get PhoneWindow.(already obtained in oncreat)
-
Calling the getDecorView() method from phoneWindow is the same as the code above.
1) Create a DecorView. 2) Get the property setting information from the XML and set it up. 3) Add the XML layout selected by attributes to the DecorView. 4) Get the controls on the layoutCopy the code
-
Create a subDecor ViewGroup and add a layout to replace the Content in the DecorView. Modify the control ID in subDecor to be the same as the ViewGroup in the DecorView. (viewGroup is the XML for the activity)
PhoneWindow.java
[mContext].inflate(ID, layout, Boolean)
1.LayoutInflate.inflate()
XML layout files are parsed to prepare for subsequent creation of individual control layouts.
LayoutInflate.java
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) { synchronized (mConstructorArgs) { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate"); final Context inflaterContext = mContext; final AttributeSet attrs = Xml.asAttributeSet(parser); Context lastContext = (Context) mConstructorArgs[0]; mConstructorArgs[0] = inflaterContext; View result = root; // Create the root layout try {advanceToRootNode(parser); final String name = parser.getName(); if (DEBUG) { System.out.println("**************************"); System.out.println("Creating root view: " + name); System.out.println("**************************"); } // Determine whether the root tag of the XML is a merge tag. If (TAG_MERGE. Equals (name)) {/ / if it is, there is no root or attachToRoot is false, throw exceptions collapse if (root = = null | |! attachToRoot) { throw new InflateException("<merge /> can be used only with a valid " + "ViewGroup root and attachToRoot=true"); } rInflate(parser, root, inflaterContext, attrs, false); } else {// Temp is the root view that was found in the XML // Create the root view by reflection. final View temp = createViewFromTag(root, name, inflaterContext, attrs); ViewGroup.LayoutParams params = null; //root is not empty if (root! = null) { if (DEBUG) { System.out.println("Creating params from root: " + root); } // Create layout params that match root, if supplied // Get parent layout parameters. params = root.generateLayoutParams(attrs); // If attachToRoot is false if (! attachToRoot) { // Set the layout params for temp if we are not // attaching. (If we are, we use addView, // Pass the parameters of the root layout to the newly created root view. temp.setLayoutParams(params); }// Otherwise, no pass. } if (DEBUG) { System.out.println("-----> start inflating children"); } // Inflate all children under temp against its context. rInflateChildren(parser, temp, attrs, true); if (DEBUG) { System.out.println("-----> done inflating children"); } // We are supposed to attach all the views we found (int temp) // to root. Do that now. // The root layout is not Null,attachToRoot, then call addView () if (root! = null && attachToRoot) { root.addView(temp, params); } // Decide whether to return the root that was passed in or the // top view found in xml. if (root == null || ! attachToRoot) { result = temp; } } } catch (XmlPullParserException e) { final InflateException ie = new InflateException(e.getMessage(), e); ie.setStackTrace(EMPTY_STACK_TRACE); throw ie; } catch (Exception e) { final InflateException ie = new InflateException( getParserStateDescription(inflaterContext, attrs) + ": " + e.getMessage(), e); ie.setStackTrace(EMPTY_STACK_TRACE); throw ie; } finally { // Don't retain static reference on context. mConstructorArgs[0] = lastContext; mConstructorArgs[1] = null; Trace.traceEnd(Trace.TRACE_TAG_VIEW); } // Return root layout return result; }}Copy the code
2. Create subviews, recursively
void rInflate(XmlPullParser parser, View parent, Context context, AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException { final int depth = parser.getDepth(); int type; boolean pendingRequestFocus = false; while (((type = parser.next()) ! = XmlPullParser.END_TAG || parser.getDepth() > depth) && type ! = XmlPullParser.END_DOCUMENT) { if (type ! = XmlPullParser.START_TAG) { continue; } final String name = parser.getName(); if (TAG_REQUEST_FOCUS.equals(name)) { pendingRequestFocus = true; consumeChildElements(parser); } else if (TAG_TAG.equals(name)) { parseViewTag(parser, parent, attrs); } else if (tag_include.equals (name)) {//include tag cannot be root if (parser.getDepth() == 0) {throw new InflateException("<include /> cannot be the root element"); } parseInclude(parser, context, parent, attrs); } else if (tag_merge.equals (name)) {// If there is a merge in the sub-layout, an exception is thrown. throw new InflateException("<merge /> must be the root element"); } else { final View view = createViewFromTag(parent, name, context, attrs); final ViewGroup viewGroup = (ViewGroup) parent; final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs); rInflateChildren(parser, view, attrs, true); viewGroup.addView(view, params); } } if (pendingRequestFocus) { parent.restoreDefaultFocus(); } if (finishInflate) { parent.onFinishInflate(); }}Copy the code
Ii. Interview topics
1. Where should the requestWindowFeature(window.feature_no_title) be placed? Why is that?
Answer: It needs to be on top of the setContentView.
GetWindow ().requestFeature(featureId);
The PhoneWindow setContentView is set to True at the bottom.
2. When will PhoneWindow be created
Each of the following creates a PhoneWdindow
- Activity
- Dialog
- PopupWindow
- Toast
3. Add layout results.
4. Merge, include, and ViewStub.
Merge: can only be used as a root_view to optimize layout.
Include: cannot do root_view, include layout, id will be replaced by the id in the include.
Viewstub: similar to the root include, can be lazily loaded, hidden by default.