The Process of adding for View and Windows of Android

Introduce

For a deep understanding for mechanism of view, it’s necessary to introducing the process of addView. However, as View, Windows is also a part showing to user. So the process of adding Window will introduced as well.

Adding View

The main part of adding process happens in the addView function.

Sour Code Insight For addView() in ViewGroup.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

/*
* /android/4.0.3/frameworks-base/core/java/android/view/ViewGroup.java
*/

if (child == null) {
throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
}

// addViewInner() will call child.requestLayout() when setting the new LayoutParams
// therefore, we call requestLayout() on ourselves before, so that the child's request
// will be blocked at our level
requestLayout();
invalidate(true);
addViewInner(child, index, params, false);

Step 1.

go to the function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

```java

if (mMeasureCache != null) mMeasureCache.clear();

if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
// Only trigger request-during-layout logic if this is the view requesting it,
// not the views in its parent hierarchy
ViewRootImpl viewRoot = getViewRootImpl();
if (viewRoot != null && viewRoot.isInLayout()) {
if (!viewRoot.requestLayoutDuringLayout(this)) {
return;
}
}
mAttachInfo.mViewRequestingLayout = this;
}

mPrivateFlags |= PFLAG_FORCE_LAYOUT;
mPrivateFlags |= PFLAG_INVALIDATED;

if (mParent != null && !mParent.isLayoutRequested()) {
mParent.requestLayout();
}
if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
mAttachInfo.mViewRequestingLayout = null;
}

Step1.1 why

and what is it ?
1
2
3
4
5

It is assigned value at ```measure()``` as follows:
```java
mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
(long) mMeasuredHeight & 0xffffffffL); // suppress sign extension

what is

key
1
2
3
4
5
6
7
8
9
10

```widthMeasureSpec``` is int type, the result key is the mMeasureWidth+mMeasureHeight

Step1.2 ```mAttachInfo``` and ```mAttachInfo.mViewRequestingLayout``` is what ?
```mAttachInfo``` inherit from parent, source is viewroot.


Step1.3 ParentView requestLayout()

Step2 ```invalidate(true)``` is for setting the area and letting child ```invalidate()

Step3 The main content is in addViewInner(), code as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
if (child.getParent() != null) {
throw new IllegalStateException("The specified child already has a parent. " +
"You must call removeView() on the child's parent first.");
}

if (!checkLayoutParams(params)) {
params = generateLayoutParams(params);
}

if (preventRequestLayout) {
child.mLayoutParams = params;
} else {
child.setLayoutParams(params);
}

if (index < 0) {
index = mChildrenCount;
}

addInArray(child, index);

// tell our children
if (preventRequestLayout) {
child.assignParent(this);
} else {
child.mParent = this;
}

if (child.hasFocus()) {
requestChildFocus(child, child.findFocus());
}

AttachInfo ai = mAttachInfo;
if (ai != null) {
boolean lastKeepOn = ai.mKeepScreenOn;
ai.mKeepScreenOn = false;
child.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK));
if (ai.mKeepScreenOn) {
needGlobalAttributesUpdate(true);
}
ai.mKeepScreenOn = lastKeepOn;
}

if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewAdded(this, child);
}

if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) {
mGroupFlags |= FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE;
}

add view in viewgroup’s array. The other operaions are for

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

In the end, the View is added in the Group and showed.

### Add Window
Let Dialog as an example, Dialog construction function as follows:
```java

mContext = new ContextThemeWrapper(
context, theme == 0 ? com.android.internal.R.style.Theme_Dialog : theme);
mWindowManager = (WindowManager)context.getSystemService("window");
Window w = PolicyManager.makeNewWindow(mContext);
mWindow = w;
w.setCallback(this);
w.setWindowManager(mWindowManager, null, null);
w.setGravity(Gravity.CENTER);
mUiThread = Thread.currentThread();
mListenersHandler = new ListenersHandler(this);

Dialog is attached on ContextThemeWrapper, and let WindowManger know the Window, get the Thread.

Dialog is different from PopupWindow. That will introduced.