The view. post(Runnable Action) method depends on whether mAttachInfo is empty, so when mAttachInfo is assigned, and where it comes from.
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if(attachInfo ! =null) {
return attachInfo.mHandler.post(action);
}
// Postpone the runnable until we know on which thread it needs to run.
// Assume that the runnable will be successfully placed after attach.
getRunQueue().post(action);
return true;
}
Copy the code
MAttachInfo is a member variable of View. If you search for mAttachInfo, you will find only one assignment
void dispatchAttachedToWindow(AttachInfo info, int visibility) { mAttachInfo = info; . }Copy the code
AttachInfo info, int Visibility) is not called in the View, so use the ViewGroup
private void addViewInner(View child, int index, LayoutParams params, boolean preventRequestLayout) {
...
AttachInfo ai = mAttachInfo;
if (ai != null && (mGroupFlags & FLAG_PREVENT_DISPATCH_ATTACHED_TO_WINDOW) == 0) {
boolean lastKeepOn = ai.mKeepScreenOn;
ai.mKeepScreenOn = false;
child.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK));
if (ai.mKeepScreenOn) {
needGlobalAttributesUpdate(true);
}
ai.mKeepScreenOn = lastKeepOn;
}
...
}
Copy the code
So addViewInner looks familiar, yeah, it’s the method that addView eventually calls
public void addView(View child, int index, LayoutParams params) {
if (DBG) {
System.out.println(this + " addView");
}
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);
}
Copy the code
public void addView(View child, int index) {
if (child == null) {
throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
}
LayoutParams params = child.getLayoutParams();
if (params == null) {
params = generateDefaultLayoutParams();
if (params == null) {
throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");
}
}
addView(child, index, params);
}
Copy the code
public void addView(View child) {
addView(child, -1);
}
Copy the code
When is mAttachInfo assigned to be found? Where does mAttachInfo come from?
From the View and ViewGroup code, you can see that mAttachInfo is passed in from parent, The root View is a DecorView, and the DecorView is added to a ViewRootImpl (ViewRootImpl is not a View, but it implements ViewParent, so it has addView methods). So let’s go to ViewParent
public ViewRootImpl(Context context, Display display) { ... mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this, context); . }Copy the code
The second answer is also revealed, the creation of mAttachInfo is in the ViewRootImpl constructor, that is, the creation of mAttachInfo, ViewRootImpl.