上节setcontentview的时候生成Decorview,那他怎么绑定到window上去的呢。
activitythread.java
@Override
public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
boolean isForward, String reason) {
。。。省略
//Resume the activity
if (!performResumeActivity(r, finalStateRequest, reason)) {
return;
}
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 (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
// Normally the ViewRoot sets up callbacks with the Activity
// in addView->ViewRootImpl#setView. If we are instead reusing
// the decor view we have to notify the view root that the
// callbacks may have changed.
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
//WindowsManager调用addview把decorview加进去
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.
}
windowmanage调用addview方法,然后点击进去会跑到WindowManagerGlobal方法
WindowManagerGlobal.java的addview方法
新建viewrootimpl方法
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);// DecorView
mRoots.add(root);
mParams.add(wparams);
// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView, userId);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
这里有几个类
WindowManagerImpl、WindowManagerGlobal、ViewRootImpl
WindowManagerImpl:确定 View 属于哪个屏幕,哪个父窗口
WindowManagerGlobal:管理整个进程 所有的窗口信息
ViewRootImpl:WindowManagerGlobal 实际操作者,操作自己的窗口
接下来只要看ViewRootImpl.setview方法
requestLayout();// 请求遍历
res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId,
mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,
mTempControls);// 将窗口添加到WMS上面 WindowManagerService
点击事件处理
view.assignParent(this)//设置parent
主要看requestLayout
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();//检查是不是当前线程,就是创建viewrootimpl的线程
mLayoutRequested = true;
scheduleTraversals();查看这个方法
}
}
//演舞者调用主要看mTraversalRunnable这个方法
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
走到performTraversals这个方法
measureHierarchy(host, lp, mView.getContext().getResources(),
desiredWindowWidth, desiredWindowHeight);//预测量
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);//布局窗口
performMeasure
performLayout
performDraw
总结
1.handleResumeActivity
2.windowmanage的 wm.addView(decor, l);
3.WindowManagerGlobal.addview
4.ViewRootImpl.setview
- requestLayout()
6.mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); - performTraversals里面performMeasure,performLayout,performDraw