View绘制流程代码执行流程
从ActivityThread#handleResumeActivity出发
- Activity#onResume执行流程
-->ActivityThread#performResumeActivity-->r.activity.performResume
-->Activity#performResume-->mInstrumentation.callActivityOnResume
-->wm.addView(decor, l);实际上是WindowManagerImpl#addView
-->WindowManagerGlobal#addView
...
root = new ViewRootImpl(view.getContext(), display);
mViews.add(view);//DecorView
mRoots.add(root);//ViewRootImpl
mParams.add(wparams);//WindowManager.LayoutParams
root.setView(view, wparams, panelParentView, userId);
...
WindowManagerImpl、WindowManagerGlobal、ViewRootImpl WindowManagerImpl:确定 View 属于哪个屏幕,哪个父窗口 WindowManagerGlobal:管理整个进程 所有的窗口信息 ViewRootImpl:WindowManagerGlobal 实际操作者,操作自己的窗口
ViewRootImpl的构造方法
mThread = Thread.currentThread(); // 拿到创建它的线程,MainThread --- 默认
mDirty = new Rect(); // 脏区域
mAttachInfo = new View.AttachInfo(); // 保存当前窗口的一些信息
-->ViewRootImpl#setView
...
requestLayout();
res = mWindowSession.addToDisplayAsUser // 将窗口添加到WMS上面
view.assignParent(this);// getParent ViewRootImpl
...
-->ViewRootImpl#requestLayout
-->ViewRootImpl#scheduleTraversals
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
-->ViewRootImpl#doTraversal
-->ViewRootImpl#performTraversals//View绘制流程都在这个方法里面
...
windowSizeMayChange |= measureHierarchy()// 预测量
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
performLayout(lp, mWidth, mHeight);
performDraw();
...
ViewRootImpl#performMeasure
-->View#measure
-->View#onMeasure
ViewRootImpl#performLayout
-->host.layout()//DecorView
-->View#onLayout
ViewRootImpl#performDraw
-->ViewRootImpl#draw
mAttachInfo.mThreadedRenderer.draw//硬件加速绘制
drawSoftware();//软件绘制
ViewRootImpl#drawSoftware-->mView.draw(canvas)
-->View#draw()
...
onDraw(canvas);
dispatchDraw(canvas);
...
ViewGroup为什么不会执行 onDraw ? View.draw(canvas) (DecorView) --> onDraw(canvas); 下面的流程是一个递归动作 --> dispatchDraw(canvas); (ViewGroup.dispatchDraw) --> drawChild --> View.draw(Canvas canvas, ViewGroup parent, long drawingTime) --> renderNode = updateDisplayListIfDirty(); --> dispatchDraw(canvas);
UI 刷新只能在主线程进行吗?不是 原因:调用了checkThread(); requestLayout() View.invalidate --> ... --> parent.invalidateChildInParent --> ViewRootImpl.invalidateChildInParent --> checkThread();
如何实现在子线程刷新Ui?
- 在ViewRootImpl 创建之前调用
- 在需要刷新Ui的子线程 创建ViewRootImpl