The creation process of Activity's ViewRoot (1)

When an Activity is activated for the first time, page1
creates a ViewRoot object for the Activity component and associates it with the application window created by the Activity, so that the UI display of the application window view can be controlled through the ViewRoot object. .We
start to analyze the creation process of ViewRoot from the handleResumeActivity function of ActivityThread. The handleResumeActivity function is defined as follows, we only care about the department created by ViewRoot:
1 final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
2 boolean reallyResume) {
3 // If we are getting ready to gc after going to the background, well
4 // we are back active so skip it.
5 unscheduleGcIdler();
6
7 ActivityClientRecord r = performResumeActivity(token, clearHide);
8
9 if (r != null) {
10 final Activity a = r.activity;
11
12             if (localLOGV) Slog.v(
13                 TAG, "Resume " + r + " started activity: " +
14                 a.mStartedActivity + ", hideForNow: " + r.hideForNow
15                 + ", finished: " + a.mFinished);
16
17             final int forwardBit = isForward ?
18                     WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
19
20             // If the window hasn't yet been added to the window manager,
21             // and this guy didn't finish itself or start another activity,
22             // then go ahead and add the window.
23             boolean willBeVisible = !a.mStartedActivity;
24             if (!willBeVisible) {
25                 try {
26                     willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
27                             a.getActivityToken());
28                 } catch (RemoteException e) {
29                 }
30             }
31             if (r.window == null && !a.mFinished && willBeVisible) {
32                 r.window = r.activity.getWindow();
33                 View decor = r.window.getDecorView();
34                 decor.setVisibility(View.INVISIBLE);
35                 ViewManager wm = a.getWindowManager();
36                 WindowManager.LayoutParams l = r.window.getAttributes();
37                 a.mDecor = decor;
38                 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
39                 l.softInputMode |= forwardBit;
40                 if (a.mVisibleFromClient) {
41                     a.mWindowAdded = true;
42                     wm.addView(decor, l);
43                 }
44
45             // If the window has already been added, but during resume
46             // we started another activity, then don't yet make the
47             // window visible.
48             } else if (!willBeVisible) {
49                 if (localLOGV) Slog.v(
50                     TAG, "Launch " + r + " mStartedActivity set");
51                 r.hideForNow = true;
52             }
53
54             // Get rid of anything left hanging around.
55             cleanUpPendingRemoveWindows(r);
56
57             // The window is now visible if it has been added, we are not
58             // simply finishing, and we are not starting another activity.
59             if (!r.activity.mFinished && willBeVisible
60                     && r.activity.mDecor != null && !r.hideForNow) {
61                 if (r.newConfig != null) {
62                     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
63                             + r.activityInfo.name + " with newConfig " + r.newConfig);
64                     performConfigurationChanged(r.activity, r.newConfig);
65                     freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.newConfig));
66                     r.newConfig = null;
67                 }
68                 if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
69                         + isForward);
70                 WindowManager.LayoutParams l = r.window.getAttributes();
71                 if ((l.softInputMode
72                         & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
73                         != forwardBit) {
74                     l.softInputMode = (l.softInputMode
75                             & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
76                             | forwardBit;
77                     if (r.activity.mVisibleFromClient) {
78                         ViewManager wm = a.getWindowManager();
79                         View decor = r.window.getDecorView();
80                         wm.updateViewLayout(decor, l);
81                     }
82                 }
83                 r.activity.mVisibleFromServer = true;
84                 mNumVisibleActivities++;
85                 if (r.activity.mVisibleFromClient) {
86                     r.activity.makeVisible();
87                 }
88             }
89
90             if (!r.onlyLocalRequest) {
91                 r.nextIdle = mNewActivities;
92                 mNewActivities = r;
93                 if (localLOGV) Slog.v(
94                     TAG, "Scheduling idle handler for " + r);
95                 Looper.myQueue().addIdleHandler(new Idler());
96             }
97             r.onlyLocalRequest = false;
98
99             // Tell the activity manager we have resumed.
100             if (reallyResume) {
101                 try {
102                     ActivityManagerNative.getDefault().activityResumed(token);
103                 } catch (RemoteException ex) {
104                 }
105             }
106
107         } else {
108             // If an exception was thrown when trying to resume, then
109             // just end this activity.
110             try {
111                 ActivityManagerNative.getDefault()
112                     .finishActivity(token, Activity.RESULT_CANCELED, null);
113 } catch (RemoteException ex) {
114 }
115 }
116 }
Line 31 (ActivityThread->handleResumeActivity) r.window == null means that Activity has not been associated with Window, so it will enter lines 32-47 (ActivityThread->handleResumeActivity) ) code.
    Line 32 (ActivityThread->handleResumeActivity) will assign r.window to r.activity.getWindow(), which is the Window of the Activity component.
    Line 33 (ActivityThread->handleResumeActivity) will assign r.window. getDecorView(), that is, the DecorView is taken out. If the current DecorView has not been created, a DecorView object will be created. For a detailed analysis of the PhoneWindow's getDecorView function, please refer to the page9 document.
Line 35 (ActivityThread->handleResumeActivity) calls the Activity's The getWindowManager function to get the WindowManager, in fact, it gets a WindowManagerImpl object.
Line 37 (ActivityThread->handleResumeActivity) sets the mDecor of the Activity to r.window.getDecorView()
    Line 41 (ActivityThread->handleResumeActivity) sets the mWindowAdded of the Activity to true, indicating that the Activity already has a Window.
    Line 42 (ActivityThread->handleResumeActivity) will call the addView function of WindowManagerImpl. For a detailed analysis of the addView function, please refer to the page2 file
.page2 The definition of
the addView function of WindowManagerImpl is as follows:
public void addView(View view, ViewGroup.LayoutParams params) {
        mGlobal.addView(view, params, mDisplay, mParentWindow);
    }
The type of mGlobal is WindowManagerGlobal, and the definition of the addView function of WindowManagerGlobal is as follows :
1 public void addView(View view, ViewGroup.LayoutParams params,
2 Display display, Window parentWindow) {
3 if (view == null) {
4 throw new IllegalArgumentException("view must not be null");
5         }
6         if (display == null) {
7             throw new IllegalArgumentException("display must not be null");
8         }
9         if (!(params instanceof WindowManager.LayoutParams)) {
10             throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
11         }
12
13         final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
14         if (parentWindow != null) {
15             parentWindow.adjustLayoutParamsForSubWindow(wparams);
16         }
17
18         ViewRootImpl root;
19         View panelParentView = null;
20
21         synchronized (mLock) {
22             // Start watching for system property changes.
23             if (mSystemPropertyUpdater == null) {
24                 mSystemPropertyUpdater = new Runnable() {
25                     @Override public void run() {
26                         synchronized (mLock) {
27                             for (ViewRootImpl viewRoot : mRoots) {
28                                 viewRoot.loadSystemProperties();
29                             }
30                         }
31                     }
32                 };
33                 SystemProperties.addChangeCallback(mSystemPropertyUpdater);
34             }
35
36             int index = findViewLocked(view, false);
37             if (index >= 0) {
38                 throw new IllegalStateException("View " + view
39                         + " has already been added to the window manager.");
40             }
41
42             // If this is a panel window, then find the window it is being
43             // attached to for future reference.
44             if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
45                     wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
46                 final int count = mViews != null ? mViews.length : 0;
47                 for (int i=0; i<count; i++) {
48                     if (mRoots[i].mWindow.asBinder() == wparams.token) {
49                         panelParentView = mViews[i];
50                     }
51                 }
52             }
53
54             root = new ViewRootImpl(view.getContext(), display);
55
56             view.setLayoutParams(wparams);
57
58             if (mViews == null) {
59                 index = 1;
60                 mViews = new View[1];
61                 mRoots = new ViewRootImpl[1];
62                 mParams = new WindowManager.LayoutParams[1];
63             } else {
64                 index = mViews.length + 1;
65                 Object[] old = mViews;
66                 mViews = new View[index];
67                 System.arraycopy(old, 0, mViews, 0, index-1);
68                 old = mRoots;
69                 mRoots = new ViewRootImpl[index];
70                 System.arraycopy(old, 0, mRoots, 0, index-1);
71                 old = mParams;
72                 mParams = new WindowManager.LayoutParams[index];
73                 System.arraycopy(old, 0, mParams, 0, index-1);
74             }
75             index--;
76
77             mViews[index] = view;
78             mRoots[index] = root;
79             mParams[index] = wparams;
80         }
81
82         // do this last because it fires off messages to start doing things
83         try {
84             root.setView(view, wparams, panelParentView);
85         } catch (RuntimeException e) {
86             // BadTokenException or InvalidDisplayException, clean up.
87             synchronized (mLock) {
88                 final int index = findViewLocked(view, false);
89                 if (index >= 0) {
90                     removeViewLocked(index, true);
91                 }
92             }
93 throw e;
94 }
95 }

Lines 3-11 (WindowManagerGlobal->addView) judge the correctness of the input parameters
Lines 13-16 (WindowManagerGlobal->addView) call adjustLayoutParamsForSubWindow of parentWindow when parentWindow is not null The function to notify the parent window that
    line 21 (WindowManagerGlobal->addView) will lock on mLock, in order to protect the access of the three arrays mViews, mRoots, mParams.
    Lines 23-34 (WindowManagerGlobal->addView) will register a The observer of the system property change
    line 36 (WindowManagerGlobal->addView) will call the findViewLocked function to find out whether ViewRoot has been created. For a detailed analysis of the findViewLocked function, please refer to the page3 file
    . Line 37-40 (WindowManagerGlobal->addView) found that it has been The Activity has created a ViewRoot, and an exception will be thrown
    . Lines 44-52 (WindowManagerGlobal->addView) are in the Window of the panel type, then the panelParentView will be found out, then what is the Window of the Panel type, it should be attached to In other windows, i am not sure.
    Line 54 (WindowManagerGlobal->addView) creates a ViewRootImpl and assigns it to the temporary variable root. For the creation process of ViewRootImpl, please refer to the page4 file.
    Line 56 (WindowManagerGlobal->addView) will
    line 58-79 (WindowManagerGlobal-> addView) will save View, ViewRootImpl and LayoutParams to the mViews, mRoots and mParams arrays. During this process, the System.arraycopy function will be used to move the arrays. Isn't this slow?
    Lines 83-94 (WindowManagerGlobal-> addView) will call the setView function of ViewRootImpl. Once an exception occurs in the setView function, the View will be deleted from WindowManagerGlobal. For a detailed analysis of the setView function of ViewRootImpl, please refer to the page8 file.
page3
In this article, we analyze The implementation of the findViewLocked function of the WindowManagerGlobal class:
1 private int findViewLocked(View view, boolean required) {
2 if (mViews != null) {
3 final int count = mViews.length;
4 for (int i = 0; i < count; i++) {
5 if (mViews[i] == view) {
6 return i;
7 }
8 }
9 }
10 if (required) {
11 throw new IllegalArgumentException("View not attached to window manager");
12 }
13 return -1;
14 }

The logic of the findViewLocked function is very simple, that is, it searches linearly in the mViews array and returns the index number, if not found, it returns -1.




Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326069935&siteId=291194637