android 通过代码创建一个画布,Android Canvas的由来

1:前言

在绘制过程中首先得了解几个比较重要的概念

Window的类型和级别

Surface是干什么的

View中的ondraw方法里的Canvas对象是哪来的?

WMS添加Window的过程,和事件传递机制

2:Surface

其实可以把它理解成是真正的画布,我们应用绘制View用的Canvas就是通过Surface来创建的,每一个Window中都存在一个自己的Surface,这个声明在ViewRootImpl中,但是ViewRootImpl中声明的Surface只是一个空壳,在绘制之前会调用relayoutWindow到WMS中去真正的创建Surface,它需要通过系统的SurfaceFlinger来整合显示,简单说就是Window需要通过Surface创建的Canvas来绘制要显示的内容,然后系统底层来控制Surface的整合展示,我们看来看一下Surface真正的创建过程和Canvas是怎么得来的

2.1:ViewRootImpl之Surface申明

ViewRootImpl中声明的Surface

final Surface mSurface = new Surface();

2.2:ViewRootImpl::performTraversals

在ViewRootImpl的绘制方法中,也就是performTraversals中会在执行performDraw之前先去WMS端获取到native层Sureface

private void performTraversals() {

//顶层的View,可以理解成是DecorView

final View host = mView;

...

//通知被添加到窗口了,传入了mAttachInfo

host.dispatchAttachedToWindow(mAttachInfo, 0);

//调用relayoutWindow方法去获取native层的Surface

relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);

...

//measure过程

performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);

....

//layout过程

performLayout(lp, desiredWindowWidth, desiredWindowHeight);

....

//通知layout完成了

mAttachInfo.mTreeObserver.dispatchOnGlobalLayout();

....

//draw过程

performDraw();

}

2.3:relayoutWindow

ViewRootImpl的relayoutWindow方法,去获取native行Surface

private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,

boolean insetsPending) throws RemoteException {

....

//调用了mWindowSession的relayout方法,上面我们知道IWindowSession真正实现是Session

int relayoutResult = mWindowSession.relayout(

mWindow, mSeq, params,

(int) (mView.getMeasuredWidth() * appScale + 0.5f),

(int) (mView.getMeasuredHeight() * appScale + 0.5f),

viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,

mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,

mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingConfiguration,

mSurface);//最后一个参数传入了ViewRootImpl中的空壳Sureface

....

return relayoutResult;

}

2.4:relayoutWindow

Session中的relayoutWindow

public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,

int requestedWidth, int requestedHeight, int viewFlags,

int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,

Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Rect outBackdropFrame,

Configuration outConfig, Surface outSurface) {

//直接调用了WMS的relayoutWIndow

int res = mService.relayoutWindow(this, window, seq, attrs,

requestedWidth, requestedHeight, viewFlags, flags,

outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,

outStableInsets, outsets, outBackdropFrame, outConfig, outSurface);

return res;

}

2.5:relayoutWindow

WindowManagerService中的relayoutWindow方法

public int relayoutWindow(Session session, IWindow client, int seq,

WindowManager.LayoutParams attrs, int requestedWidth,

int requestedHeight, int viewVisibility, int flags,

Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,

Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,

Configuration outConfig, Surface outSurface) {

....

//创建SurfaceControl并获取native中创建Surface

result = createSurfaceControl(outSurface, result, win, winAnimator);

....

}

2.6:createSurfaceControl

WindowManagerService中的createSurfaceControl方法

private int createSurfaceControl(Surface outSurface, int result, WindowState win,

WindowStateAnimator winAnimator) {

if (!win.mHasSurface) {

result |= RELAYOUT_RES_SURFACE_CHANGED;

}

WindowSurfaceController surfaceController = winAnimator.createSurfaceLocked();

if (surfaceController != null) {

//获取native层的Surface

surfaceController.getSurface(outSurface);

} else {

outSurface.release();

}

return result;

}

2.7:getSurface

WindowSurfaceController中的getSurface方法

void getSurface(Surface outSurface) {

//调用了Surface中的copyFrom方法,从方法名体现的是将native层的Surface复制到客户端的空壳中

outSurface.copyFrom(mSurfaceControl);

}

3:Canvas的创建

在调用draw之前会先创建Canvas对象

private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,

boolean scalingRequired, Rect dirty) {

final Canvas canvas;

try {

//使用Surface创建一个Canvas,方法中也是调用了native方法

anvas = mSurface.lockCanvas(dirty);

if (left != dirty.left || top != dirty.top || right != dirty.right

|| bottom != dirty.bottom) {

attachInfo.mIgnoreDirtyState = true;

}

canvas.setDensity(mDensity);

}catch (Surface.OutOfResourcesException e) {

handleOutOfResourcesException(e);

return false;

} catch (IllegalArgumentException e) {

mLayoutRequested = true; // ask wm for a new surface next time.

return false;

}

....

try {

canvas.translate(-xoff, -yoff);

if (mTranslator != null) {

mTranslator.translateCanvas(canvas);

}

canvas.setScreenDensity(scalingRequired ? mNoncompatDensity : 0);

attachInfo.mSetIgnoreDirtyState = false;

//调用View的draw方法,并传入刚刚创建的Canvas对象

mView.draw(canvas);

drawAccessibilityFocusedDrawableIfNeeded(canvas);

} finally {

if (!attachInfo.mSetIgnoreDirtyState) {

// Only clear the flag if it was not set during the mView.draw() call

attachInfo.mIgnoreDirtyState = false;

}

}

....

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值