Android GUI Activity, Window, View, and androidactivity
I believe that you have already known The Role Of The setContentView method in the Activity at the beginning of your access to Android. It is obvious that this method is used to fill the corresponding layout for the Activity. Then, how does the Activity draw the filled layout? In fact, the Activity draws and displays the View to the Window object for processing. The following uses the source code for tracking and analysis.
The source code of the Activity is as follows. Only the following content is shown:
public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory2, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks2, Window.OnWindowDismissedCallback { …… …… private Window mWindow; private WindowManager mWindowManager; …… /** * Retrieve the current {@link android.view.Window} for the activity. * This can be used to directly access parts of the Window API that * are not available through Activity/Screen. * * @return Window The current window, or null if the activity is not * visual. */ public Window getWindow() { return mWindow; } …… /** * 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. * * @see #setContentView(android.view.View) * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams) */ public void setContentView(int layoutResID) { getWindow().setContentView(layoutResID); initWindowDecorActionBar(); } /** * Set the activity content to an explicit view. This view is placed * directly into the activity's view hierarchy. It can itself be a complex * view hierarchy. When calling this method, the layout parameters of the * specified view are ignored. Both the width and the height of the view are * set by default to {@link ViewGroup.LayoutParams#MATCH_PARENT}. To use * your own layout parameters, invoke * {@link #setContentView(android.view.View,android.view.ViewGroup.LayoutParams)} * instead. * * @param view The desired content to display. * * @see #setContentView(int) * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams) */ public void setContentView(View view) { getWindow().setContentView(view); initWindowDecorActionBar(); } final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, IVoiceInteractor voiceInteractor) { attachBaseContext(context); mFragments.attachActivity(this, mContainer, null); mWindow = PolicyManager.makeNewWindow(this); …… }……}
Some source code of PolicyManager:
public final class PolicyManager { ……private static final IPolicy sPolicy; static { // Pull in the actual implementation of the policy at run-time …… sPolicy = (IPolicy)policyClass.newInstance(); …… } // Cannot instantiate this class private PolicyManager() {} // The static methods to spawn new policy-specific objects public static Window makeNewWindow(Context context) { return sPolicy.makeNewWindow(context); } ……}
Partial Policy source code:
public class Policy implements IPolicy { …… public Window makeNewWindow(Context context) { return new PhoneWindow(context);}……}
From the source code, we can see that the Activity contains a Window-type object mWindow. When we call the setContentView method, it is actually delegated to the Window object for processing. Window itself is an abstract class that describes the basic attributes and Behavior Features of android windows. In the attach method of the activity, the Window object is created through mWindow = PolicyManager. makeNewWindow (this. The tracing Code shows that PolicyManager. makeNewWindow (this) is actually calling the makeNewWindow method in the Policy. A PhoneWindow object is created in this method. PhoneWindow is a subclass of Window. Their relationship diagram is as follows:
Continue to trace the source code. PhoneWindow implements the abstract method setContentView (int layoutResId) of Window. The specific source code is as follows:
@Override public void setContentView(int layoutResID) { // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window // decor, when theme attributes and the like are crystalized. Do not check the feature // before this happens. if (mContentParent == null) { installDecor(); } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) { mContentParent.removeAllViews(); } if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID, getContext()); transitionTo(newScene); } else { mLayoutInflater.inflate(layoutResID, mContentParent); } final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { cb.onContentChanged(); } }
In this method, we can see that the mContentParent is first judged. If it is null, The installDecor method is called to determine whether the window has certain features through hasFeature. If the window does not contain FEATURE_CONTENT_TRANSITIONS, clear all child elements in mContentParent and prepare for loading the layout file to mContentParent. Based on the following judgment, we can also see that no matter which branch is used, the layout content of mContentParent is actually updated. From this we can infer that mContentParent is actually the storage container of our own layout, which is defined in PhoneWindow as follows:
// This is the view in which the window contents are placed. It is either // mDecor itself, or a child of mDecor where the contents go. private ViewGroup mContentParent;
Where is mContentParent created? Obviously, In the method installDecor, the key code of the method installDecor is as follows:
private void installDecor() { if (mDecor == null) { mDecor = generateDecor(); …… } if (mContentParent == null) {mContentParent = generateLayout(mDecor); …… }}
In this method, we can see that the mDecor is first judged. If it is null, The generateDecor method is called to generate the mDecor object. What is the mDecor object? By viewing the code, you can know that the mDecor type is DecorView, which is an internal class defined in PhoneWindow and inherits FrameLayout. Then determine whether mContentParent is null. If it is null, call generateLayout and generate the mContentParent object by passing in the mDecor parameter. In this method, the layout resources used are determined by applying themes and window features, and the layout is added to mDecor, these la s contain a ViewGroup (FrameLayout) with the content id. This ViewGroup is exactly the mContentParent. The key code for this method is as follows:
protected ViewGroup generateLayout(DecorView decor) { …… View in = mLayoutInflater.inflate(layoutResource, null); decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); mContentRoot = (ViewGroup) in; ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); …… return contentParent; }
Therefore, we can determine that the display and processing sequence of the view is Activity> PhoneWindow> DecorView> ViewGroup (mContentView)> Custom View (layout ).
Shows the view hierarchy in the Activity as follows:
For questions or technical exchanges, please join the official QQ group: (452379712)
Author: Jerry Education
Source: http://www.cnblogs.com/jerehedu/
The copyright of this article belongs to Yantai Jerry Education Technology Co., Ltd. and the blog Park. You are welcome to repost it. However, you must keep this statement without the author's consent and provide the original article connection on the article page, otherwise, you are entitled to pursue legal liability.