视图的测量,布局和渲染都在ViewRootImpl类中,performTraversals方法,在编舞者的控制下,当App收到刷新命令,实现一次绘制刷新。此处省略 measure layout 。
private void performTraversals(){
if (!cancelDraw && !newSurface) {//前面已经过测量与布局,且存在Surface。
performDraw();
} else {
}
}
//ViewRootImpl#performDraw方法。
private void performDraw() {
final boolean fullRedrawNeeded = mFullRedrawNeeded;
try {
draw(fullRedrawNeeded);
} finally {
}
}
此时的draw 只是更新 DIsplayList ,更新结束后,调用 syncAndDrawFrame ,
通知渲染线程开始工作,主线程从此 释放。
渲染线程的核心实现在 libhwui 库里面,其代码位于 frameworks/base/libs/hwui RenderProxy.syncAndDrawFrame
主线程负责处理进程 Message、处理 Input 事件、处理 Animation 逻辑、处理 Measure、Layout、Draw ,更新 DIsplayList ,
但是不涉及 SurfaceFlinger 打交道;渲染线程负责渲染渲染相关的工作,一部分工作也是 CPU 来完成的,一部分操作是调用 OpenGL 函数来完成的
当启动硬件加速后,在 Measure、Layout、Draw 的 Draw 这个环节,Android 使用 DisplayList 进行绘制而非直接使用 CPU 绘制每一帧。
DisplayList 是一系列绘制操作的记录,抽象为 RenderNode 类,这样间接的进行绘制操作的优点如下
DisplayList 可以按需多次绘制而无须同业务逻辑交互
*/
//入参view是顶层视图DecorView。/
void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks) {
attachInfo.mIgnoreDirtyState = true;
final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer;
choreographer.mFrameInfo.markDrawStart();
// 第一步 绘制整个树形视图结构,从顶层视图开始,每一个视图节点逐一绘制,最终目的是触发每一个视图的Canvas#drawXxx方法。
updateRootDisplayList(view, callbacks);
attachInfo.mIgnoreDirtyState = false;
// register animating rendernodes which started animating prior to renderer
// creation, which is typical for animators started prior to first draw
if (attachInfo.mPendingAnimatingRenderNodes != null) {
final int count = attachInfo.mPendingAnimatingRenderNodes.size();
for (int i = 0; i < count; i++) {
registerAnimatingRenderNode(
attachInfo.mPendingAnimatingRenderNodes.get(i));
}
attachInfo.mPendingAnimatingRenderNodes.clear();
// We don't need this anymore as subsequent calls to
// ViewRootImpl#attachRenderNodeAnimator will go directly to us.
attachInfo.mPendingAnimatingRenderNodes = null;
}
final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;
第二步 同步绘制帧。最终目的OpenGL指令写入gpu
int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);
if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
setEnabled(false);
attachInfo.mViewRootImpl.mSurface.release();
// Invalidate since we failed to draw. This should fetch a Surface
// if it is still needed or do nothing if we are no longer drawing
attachInfo.mViewRootImpl.invalidate();
}
if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
attachInfo.mViewRootImpl.invalidate();
}
}
在ViewRootImpl的setView方法中。
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
...
//view是DecorView视图,它实现RootViewSurfaceTaker
if (view instanceof RootViewSurfaceTaker) {
mSurfaceHolderCallback =((RootViewSurfaceTaker)view).willYouTakeTheSurface();
if (mSurfaceHolderCallback != null) {
mSurfaceHolder = new TakenSurfaceHolder();
mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
}
}
if (mSurfaceHolder == null) {
enableHardwareAcceleration(attrs);//开启硬件加速
}
...
}
private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
//应用在兼容模式时,不开启
//永久进程包括系统进程在低端设备中不加速
...
//创建ThreadedRenderer对象
mAttachInfo.mHardwareRenderer = HardwareRenderer.create(mContext, translucent);
...
}
if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);//硬件渲染入口。
}
第一步中:
private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Record View#draw()");
updateViewTreeDisplayList(view); 1
if (mRootNodeNeedsUpdate || !mRootNode.isValid()) {
DisplayListCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
try {
final int saveCount = canvas.save();
canvas.translate(mInsetLeft, mInsetTop);
callbacks.onHardwarePreDraw(canvas);
//插入栅栏,隔离canvas操作
canvas.insertReorderBarrier();
//绘制顶层视图RenderNode。/ 2
canvas.drawRenderNode(view.updateDisplayListIfDirty());
canvas.insertInorderBarrier();
//回调,ViewRootImpl中实现
callbacks.onHardwarePostDraw(canvas);
canvas.restoreToCount(saveCount);
mRootNodeNeedsUpdate = false;
} finally {
mRootNode.end(canvas);
}
}
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
1小步
private void updateViewTreeDisplayList(View view) {
view.mPrivateFlags |= View.PFLAG_DRAWN;
view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
== View.PFLAG_INVALIDATED;
view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
view.updateDisplayListIfDirty(); 3
view.mRecreateDisplayList = false;
}
3 public RenderNode updateDisplayListIfDirty() {
final RenderNode renderNode = mRenderNode;
if (!canHaveDisplayList()) {
// can't populate RenderNode, don't try
return renderNode;
}
if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
|| !renderNode.isValid()
|| (mRecreateDisplayList)) {
// Don't need to recreate the display list, just need to tell our
// children to restore/recreate theirs
if (renderNode.isValid()
&& !mRecreateDisplayList) {
mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
dispatchGetDisplayList();
return renderNode; // no work needed
}
// If we got here, we're recreating it. Mark it as such to ensure that
// we copy in child display lists into ours in drawChild()
mRecreateDisplayList = true;
int width = mRight - mLeft;
int height = mBottom - mTop;
int layerType = getLayerType();
//第一步,创建DisplayListCanvas
final DisplayListCanvas canvas = renderNode.start(width, height);
canvas.setHighContrastText(mAttachInfo.mHighContrastText);
try {
if (layerType == LAYER_TYPE_SOFTWARE) {
buildDrawingCache(true);
Bitmap cache = getDrawingCache(true);
if (cache != null) {
canvas.drawBitmap(cache, 0, 0, mLayerPaint);
}
} else {// 第二步,一般视图走硬件渲染都执行下面程序
computeScroll();
canvas.translate(-mScrollX, -mScrollY);
mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
// Fast path for layouts with no backgrounds
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
dispatchDraw(canvas);//该View跳过绘制,则直接派发给子视图
if (mOverlay != null && !mOverlay.isEmpty()) {
mOverlay.getOverlayView().draw(canvas);
}
} else {
draw(canvas);
}
}
} finally {//第三步,绘制结束,保存canvas记录内容,释放画布
renderNode.end(canvas);
setDisplayListProperties(renderNode);
}
} else {
mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
}
return renderNode;
}