之前讲到:
原生View绘制流程是通过 ViewRootImpl中的Surface lockCanvas拿到一块数据空间,再通过Canvas往里面填充数据,这期我们看看Surface是如何拿到数据的
简单代码就是
```java
surface.lockCanvas()
canvas.drawXX()
surface.unlockCanvasAndPost()
```
我们先从surface是如何创建开始说起:
1、首先我们知道setContentView添加View的时候会调用ViewRootImpl的performTravals:
private void performTraversals() {
//1 layoutWindow
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
//2 测量
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
// 布局
performLayout(lp, mWidth, mHeight);
// 绘制
performDraw();
}
其中relayoutWindow:会创建 SurfaceControl对象(单独分析 TODO) 通过SurfaceControl真正创建Surface的NativeObject:
mSurface.copyFrom(mSurfaceControl);
// Surface.java
public void copyFrom(SurfaceControl other) {
//生成nativeObject对象
long newNativeObject = nativeGetFromSurfaceControl(mNativeObject, surfaceControlPtr);
updateNativeObject(newNativeObject);
}
所以我们想要知道什么是nativeObject:
//通过JNI调用到
static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz,
jlong nativeObject,
jlong surfaceControlNativeObj) {
sp<Surface> surface(ctrl->getSurface());
return reinterpret_cast<jlong>(surface.get());
}
sp<Surface> SurfaceControl::generateSurfaceLocked(){
mBbq = sp<BLASTBufferQueue>::make("bbq-adapter", mBbqChild, mWidth, mHeight, mFormat);
mSurfaceData = mBbq->getSurface(true);
return mSurfaceData;
}
这里创建了一个Native的Surface.cpp,而且出现了BufferQueue(后续分析 SurfaceFlinger和BufferQueue)
拿到Surface对象后:
通过 Surface.lockCanvas获取Canvas:
public Canvas lockCanvas(Rect inOutDirty)
throws Surface.OutOfResourcesException, IllegalArgumentException {
synchronized (mLock) {
mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
return mCanvas;
}
Native层逻辑: