“This is the 12th day of my participation in the First Challenge 2022. For details: First Challenge 2022”

A DecorView is the root view of the Activity window. It is not the view that is presented to the user. The final view is the window. Window, so when you create a DecorView, you need to pass the DecorView or pass it to the Window, the Window, to display it to the user, and how do you pass it to the Window, the WindowMangaer that we’re going to introduce next.

Window

Window is the top Window in Android, which means the main Window. It has two implementation classes, PhoneWindow and MidWindow. Our general activity corresponds to PhoneWindow. Methods such as setContentView, which are often used in activities, are also implemented in this.

@Override public void setContentView(View view,ViewGroup.LayoutParams params) {undefined if (mContentParent == null) { installDecor(); } else { mContentParent.removeAllViews(); } mContentParent.addView(view, params); final Callback cb = getCallback(); if (cb ! = null) {undefined cb.onContentChanged(); // Update window class capacity when it changes}}Copy the code

Each main window has a View called a DecorView, which is the top View in the main window (actually a ViewGroup). Inside the View are two member variables called mParent and mChildren, which manage the relationship between the parent and child of the View. And a ViewGroup is the management of a set of views. Therefore, a network of all views is established in the ViewGroup. And the final ViewGroup is attached to the main window. This makes it easy to find the specific View in the window using findViewById. Event processing in the View is also handled according to this path.

WindowManager

WindowManager is mainly used to manage some states of Windows, properties, view addition, deletion, update, window order, message collection and processing, etc. Context. GetSystemService (context.window_service) to obtain an instance of WindowManager. WindowManager inherits ViewManager, which involves three important methods of window management, respectively:

 * addView(); 

 * updateViewLayout();

 * removeView();  
Copy the code

There is also an important static class, LayoutParams, in WindowManager. It allows you to set and get some properties of the current window. Let’s start with the addView() method. In addView, LayoutParams is used to get the View properties of the window, and ViewRoot is created for each window. ViewRoot is a bridge between the View and WindowManager. What actually passes the View to WindowManager is the setView() method of ViewRoot, which implements the message passing between the View and WindowManager. When you add the main window to a Windows manager, it first creates a proxy object:

 wm=(WindowManagerImpl)context.getSystemService(Context.WINDOW_SERVICE)
Copy the code

And opens a session (IWindowSession) through which the Window will then establish contact with WindowManager

Look at the handleResumeActivity method in ActivityThread:

// ActivityThread public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward, String reason) { ...... final int forwardBit = isForward ? WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0; // If the window hasn't yet been added to the window manager, // and this guy didn't finish itself or start another activity, // then go ahead and add the window. boolean willBeVisible = ! a.mStartedActivity; if (! willBeVisible) { try { willBeVisible = ActivityManager.getService().willActivityBeVisible( a.getActivityToken()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } if (r.window == null && ! a.mFinished && willBeVisible) { r.window = r.activity.getWindow(); View decor = r.window.getDecorView(); decor.setVisibility(View.INVISIBLE); ViewManager wm = a.getWindowManager(); WindowManager.LayoutParams l = r.window.getAttributes(); a.mDecor = decor; l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; l.softInputMode |= forwardBit; . if (a.mVisibleFromClient) { if (! a.mWindowAdded) { a.mWindowAdded = true; wm.addView(decor, l); } else { // The activity will get a callback for this {@link LayoutParams} change // earlier. However, at that time the decor will not be set (this is set // in this method), so no action will be taken. This call ensures the // callback occurs with the decor set. a.onWindowAttributesChanged(l);  } } // If the window has already been added, but during resume // we started another activity, then don't yet make the // window visible. } else if (! willBeVisible) { if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set"); r.hideForNow = true; } // Get rid of anything left hanging around. cleanUpPendingRemoveWindows(r, false /* force */); // The window is now visible if it has been added, we are not // simply finishing, and we are not starting another activity. if (! r.activity.mFinished && willBeVisible && r.activity.mDecor ! = null && ! r.hideForNow) { if (r.newConfig ! = null) { performConfigurationChangedForActivity(r, r.newConfig); if (DEBUG_CONFIGURATION) { Slog.v(TAG, "Resuming activity " + r.activityInfo.name + " with newConfig " + r.activity.mCurrentConfig); } r.newConfig = null; } if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" + isForward); WindowManager.LayoutParams l = r.window.getAttributes(); if ((l.softInputMode & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) ! = forwardBit) { l.softInputMode = (l.softInputMode & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)) | forwardBit; if (r.activity.mVisibleFromClient) { ViewManager wm = a.getWindowManager(); View decor = r.window.getDecorView(); wm.updateViewLayout(decor, l); } } r.activity.mVisibleFromServer = true; mNumVisibleActivities++; If (state Richard armitage ctivity. MVisibleFromClient) {/ / here will call addview state Richard armitage ctivity. MakeVisible (); } } r.nextIdle = mNewActivities; mNewActivities = r; if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r); Looper.myQueue().addIdleHandler(new Idler()); }Copy the code

First, get a DecorView and add it to the WindowManager window using the addView method. Second, when the user triggers the interface refresh mechanism, the WindowManager updateViewLayout method is called to update the layout. Third: Call the Activity’s makeVisible, make the view visible, and add the DecorView to the WindowManager if it isn’t already there

Now look at what the AddView method does:

// WindowManagerGlobal public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { // ...... root = new ViewRootImpl(view.getContext(), display); view.setLayoutParams(wparams); mViews.add(view); mRoots.add(root); mParams.add(wparams); // do this last because it fires off messages to start doing things try { root.setView(view, wparams, panelParentView); } catch (RuntimeException e) { // BadTokenException or InvalidDisplayException, clean up. if (index >= 0) { removeViewLocked(index, true); } throw e; }}Copy the code

The addView method instantiates a ViewRootImpl, calls the setView method to hold a reference to the DecorView, and holds instances of the DecorView, Params, and ViewRootImpl.

The handleResumeActivity method makes it clear why the View is visible when OnResume is used.

In fact, View drawing is done by View Rotimpl. Each application window’s DecorView has a ViewRootImpl object associated with it, and this association is maintained by WindowManager.

So in the next article, let’s focus on View View PL, how does it take care of drawing a View