View绘制流程

161 阅读1分钟

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?

  1. 在ViewRootImpl 创建之前调用
  2. 在需要刷新Ui的子线程 创建ViewRootImpl