SV继承自View,但是并不是利用View的Draw来进行绘制。而是直接跟SurfaceFlinger进行通信。那么看下具体SV是怎么实现这个功能的,它的用法如何?
还是先从构造方法开始看起。

  public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);//Enable callbacks for position changes. mRenderNode.requestPositionUpdates(this);//此方法规定不会走正常的draw方法。setWillNotDraw(true);}

假设我们直接贴一个SurfaceView 到布局中,给SV一定宽高,SV会形成一个"黑洞"区域。如图。

现在来分析下这是如何形成的。
由于SV也是一个View,只是绘制的时候会走自己的绘制机制。对于常规的onMesure和onLayout还是一样会跑的。这个也是SV得以能够进行绘制的前提条件,因为你必须首先有大小,然后有位置,其次才是在具体位置利用画笔(paint)进行绘制的。那么先来看看onMeasure。

@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//mRequestedWidth 由setFixedSize设置,默认情况是-1。那么默认是走getDefaultSize.也就是基本的测量方法。int width = mRequestedWidth >= 0? resolveSizeAndState(mRequestedWidth, widthMeasureSpec, 0): getDefaultSize(0, widthMeasureSpec);int height = mRequestedHeight >= 0? resolveSizeAndState(mRequestedHeight, heightMeasureSpec, 0): getDefaultSize(0, heightMeasureSpec);setMeasuredDimension(width, height);}

所以onMeasure可以说平平无奇。
接下来看下布局。发现SV并没有重写这个onLayout方法。但是有重写setFrame方法,这个方法是View中,layout过程调用的。所以布局的时候必然会走到这个setFrame方法。

/** @hide */
@Override
protected boolean setFrame(int left, int top, int right, int bottom) {boolean result = super.setFrame(left, top, right, bottom);updateSurface();return result;
}

这里面的关键方法就是updateSurface方法.

    /** @hide */protected void updateSurface() {//判断是否有长宽。经历了measure之后mHaveFrame为true.if (!mHaveFrame) {return;}//获取View 根。ViewRootImpl viewRoot = getViewRootImpl();//主要看最后一个就是说View的mSurface是否准备完毕。也就是说,必须ViewTree的surface准备完毕才会走到后面的方法。正常流程经历了onResume,surface准备完毕,才会发起requestlayout,才会有布局的。if (viewRoot == null || viewRoot.mSurface == null || !viewRoot.mSurface.isValid()) {return;}// mTranslator 属于一个转换器。   mTranslator = viewRoot.mTranslator;if (mTranslator != null) {mSurface.setCompatibilityTranslator(mTranslator);}int myWidth = mRequestedWidth;if (myWidth <= 0) myWidth = getWidth();int myHeight = mRequestedHeight;if (myHeight <= 0) myHeight = getHeight();final boolean formatChanged = mFormat != mRequestedFormat;final boolean visibleChanged = mVisible != mRequestedVisible;//判断Surface是否正在创建状态,但是没有创建完毕。从这里也可以看到SF的surface和ViewRoot的surfcace并不是同一个。final boolean creating = (mSurfaceControl == null || formatChanged || visibleChanged)&& mRequestedVisible;final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight;final boolean windowVisibleChanged = mWindowVisibility != mLastWindowVisibility;boolean redrawNeeded = false;if (creating || formatChanged || sizeChanged || visibleChanged || windowVisibleChanged) {//获取sf控件在其整个屏幕上的坐标位置,并且存储在mLocation中。getLocationInWindow(mLocation);try {final boolean visible = mVisible = mRequestedVisible;mWindowSpaceLeft = mLocation[0];mWindowSpaceTop = mLocation[1];mSurfaceWidth = myWidth;mSurfaceHeight = myHeight;mFormat = mRequestedFormat;mLastWindowVisibility = mWindowVisibility;mScreenRect.left = mWindowSpaceLeft;mScreenRect.top = mWindowSpaceTop;mScreenRect.right = mWindowSpaceLeft + getWidth();mScreenRect.bottom = mWindowSpaceTop + getHeight();if (mTranslator != null) {mTranslator.translateRectInAppWindowToScreen(mScreenRect);}final Rect surfaceInsets = getParentSurfaceInsets();mScreenRect.offset(surfaceInsets.left, surfaceInsets.top);if (creating) {//通过ViewRoot的surface创建mSurfaceSession,这个变量用于根SurfaceFlinger进行交互。mSurfaceSession = new SurfaceSession(viewRoot.mSurface);mDeferredDestroySurfaceControl = mSurfaceControl;updateOpaqueFlag();//mSurfaceControl 从字面来看就是Surface的管理类,里面主要都是native方法。mSurfaceControl = new SurfaceControlWithBackground(mSurfaceSession,"SurfaceView - " + viewRoot.getTitle().toString(),mSurfaceWidth, mSurfaceHeight, mFormat,mSurfaceFlags);} else if (mSurfaceControl == null) {return;}boolean realSizeChanged = false;mSurfaceLock.lock();try {mDrawingStopped = !visible;if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "+ "Cur surface: " + mSurface);//SC开启一次事务。SurfaceControl.openTransaction();try {//mSublayout属于一个type。SV的类型为APPLICATION_MEDIA_SUBLAYERmSurfaceControl.setLayer(mSubLayer);if (mViewVisibility) {mSurfaceControl.show();} else {mSurfaceControl.hide();}//设置Surface的位置。矩阵。if (sizeChanged || creating || !mRtHandlingPositionUpdates) {mSurfaceControl.setPosition(mScreenRect.left, mScreenRect.top);mSurfaceControl.setMatrix(mScreenRect.width() / (float) mSurfaceWidth,0.0f, 0.0f,mScreenRect.height() / (float) mSurfaceHeight);}if (sizeChanged) {mSurfaceControl.setSize(mSurfaceWidth, mSurfaceHeight);}} finally {SurfaceControl.closeTransaction();}if (sizeChanged || creating) {redrawNeeded = true;}mSurfaceFrame.left = 0;mSurfaceFrame.top = 0;if (mTranslator == null) {mSurfaceFrame.right = mSurfaceWidth;mSurfaceFrame.bottom = mSurfaceHeight;} else {float appInvertedScale = mTranslator.applicationInvertedScale;mSurfaceFrame.right = (int) (mSurfaceWidth * appInvertedScale + 0.5f);mSurfaceFrame.bottom = (int) (mSurfaceHeight * appInvertedScale + 0.5f);}final int surfaceWidth = mSurfaceFrame.right;final int surfaceHeight = mSurfaceFrame.bottom;realSizeChanged = mLastSurfaceWidth != surfaceWidth|| mLastSurfaceHeight != surfaceHeight;mLastSurfaceWidth = surfaceWidth;mLastSurfaceHeight = surfaceHeight;} finally {mSurfaceLock.unlock();}try {redrawNeeded |= visible && !mDrawFinished;SurfaceHolder.Callback callbacks[] = null;final boolean surfaceChanged = creating;if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {mSurfaceCreated = false;if (mSurface.isValid()) {//需要重建mSurfacecallbacks = getSurfaceCallbacks();for (SurfaceHolder.Callback c : callbacks) {c.surfaceDestroyed(mSurfaceHolder);}if (mSurface.isValid()) {mSurface.forceScopedDisconnect();}}}//如果正在创建,直接copyFromif (creating) {mSurface.copyFrom(mSurfaceControl);}//如果size改变。并且考虑兼容性,需要直接createFromif (sizeChanged && getContext().getApplicationInfo().targetSdkVersion< Build.VERSION_CODES.O) {mSurface.createFrom(mSurfaceControl);}//此时mSurface已经可以用了。可以愉快的进行lockCanvasif (visible && mSurface.isValid()) {if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) {mSurfaceCreated = true;mIsCreating = true;if (callbacks == null) {callbacks = getSurfaceCallbacks();}//此处就是回调callback,我们自定义SV可以在这个方法里面拿到surface。for (SurfaceHolder.Callback c : callbacks) {c.surfaceCreated(mSurfaceHolder);}}//size 改变的情形。if (creating || formatChanged || sizeChanged|| visibleChanged || realSizeChanged) {if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "+ "surfaceChanged -- format=" + mFormat+ " w=" + myWidth + " h=" + myHeight);if (callbacks == null) {callbacks = getSurfaceCallbacks();}for (SurfaceHolder.Callback c : callbacks) {c.surfaceChanged(mSurfaceHolder, mFormat, myWidth, myHeight);}}//需要重新绘制的情形。if (redrawNeeded) {if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "+ "surfaceRedrawNeeded");if (callbacks == null) {callbacks = getSurfaceCallbacks();}mPendingReportDraws++;viewRoot.drawPending();SurfaceCallbackHelper sch =new SurfaceCallbackHelper(this::onDrawFinished);sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);}}} finally {mIsCreating = false;//如果到这里还是没有创建成功,那么需要释放mSurface。if (mSurfaceControl != null && !mSurfaceCreated) {mSurface.release();// If we are not in the stopped state, then the destruction of the Surface// represents a visual change we need to display, and we should go ahead// and destroy the SurfaceControl. However if we are in the stopped state,// we can just leave the Surface around so it can be a part of animations,// and we let the life-time be tied to the parent surface.if (!mWindowStopped) {mSurfaceControl.destroy();mSurfaceControl = null;}}}} catch (Exception ex) {Log.e(TAG, "Exception configuring surface", ex);}} else {//此处else,是针对surface非初始化创建的情形,也就是surface可利用的情形。getLocationInSurface(mLocation);final boolean positionChanged = mWindowSpaceLeft != mLocation[0]|| mWindowSpaceTop != mLocation[1];final boolean layoutSizeChanged = getWidth() != mScreenRect.width()|| getHeight() != mScreenRect.height();if (positionChanged || layoutSizeChanged) { // Only the position has changedmWindowSpaceLeft = mLocation[0];mWindowSpaceTop = mLocation[1];// For our size changed check, we keep mScreenRect.width() and mScreenRect.height()// in view local space.mLocation[0] = getWidth();mLocation[1] = getHeight();mScreenRect.set(mWindowSpaceLeft, mWindowSpaceTop,mWindowSpaceLeft + mLocation[0], mWindowSpaceTop + mLocation[1]);if (mTranslator != null) {mTranslator.translateRectInAppWindowToScreen(mScreenRect);}if (mSurfaceControl == null) {return;}if (!isHardwareAccelerated() || !mRtHandlingPositionUpdates) {try {setParentSpaceRectangle(mScreenRect, -1);} catch (Exception ex) {Log.e(TAG, "Exception configuring surface", ex);}}}}}

通过这个方法,surface已经创建完毕,并且位置和大小也确定了,所以会留下一个黑洞。如果想要绘制内容,需要实现 SurfaceHolder.Callback。下面是个demo,结合我上面的分析,能够对SV的绘制机制有更深入了解。

public class SurfaceViewDemo extends SurfaceView implements SurfaceHolder.Callback{private SurfaceHolder mSurfaceHolder;private Canvas mCanvas;private Paint paint;public SurfaceViewDemo(Context context) {this(context,null,0);}public SurfaceViewDemo(Context context, AttributeSet attrs) {this(context, attrs,0);}public SurfaceViewDemo(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {mSurfaceHolder = getHolder();mSurfaceHolder.addCallback(this);setFocusable(true);setFocusableInTouchMode(true);this.setKeepScreenOn(true);paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setColor(Color.RED);paint.setStrokeWidth(5);paint.setStyle(Paint.Style.STROKE);}@Overridepublic void surfaceCreated(SurfaceHolder holder) {System.out.println("=========surfaceCreated========");new Thread(new Runnable() {@Overridepublic void run() {draw();}}).start();}private void draw() {try {System.out.println("============draw========");mCanvas = mSurfaceHolder.lockCanvas();mCanvas.drawCircle(500,500,300,paint);mCanvas.drawCircle(100,100,20,paint);} catch (Exception e) {e.printStackTrace();} finally {if (mCanvas != null)mSurfaceHolder.unlockCanvasAndPost(mCanvas);}}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {System.out.println("=========surfaceChanged========");}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {System.out.println("=========surfaceDestroyed========");}
}

通过对SurfaceView机制的分析,可以得知,实际上SV是自己独占一个Surface。好处就是摆脱了View自带的绘制机制,比如说主线程绘制,必须是VSYNC 才能绘制等缺点。

SurfaceView源码分析相关推荐

  1. android.view.surface,Android SurfaceView 源码分析及使用

    概述 SurfaceView 是 Android 中一种比较特殊的视图(View),它跟平时时候的 TextView.Button 最大的区别是它跟它的视图容器并不是在同一个视图层上,它的 UI 显示 ...

  2. android6.0源码分析之Camera API2.0下的初始化流程分析

    1.Camera2初始化的应用层流程分析 Camera2的初始化流程与Camera1.0有所区别,本文将就Camera2的内置应用来分析Camera2.0的初始化过程.Camera2.0首先启动的是C ...

  3. GLSurfaceView源码分析以及简单使用

    GLSurfaceView源码分析以及简单使用 一. GLSurfaceView 如果我们没有使用过,从名字可以看出其与OpenGL以及Surfaceview有关,GLSurfaceView有以下特点 ...

  4. android源码分析

    01_Android系统概述 02_Android系统的开发综述 03_Android的Linux内核与驱动程序 04_Android的底层库和程序 05_Android的JAVA虚拟机和JAVA环境 ...

  5. Android上百实例源码分析以及开源分析集合打包

    感谢网友banketree的收集,压缩包的内容如下: 1.360新版特性界面源代码 实现了360新版特性界面的效果,主要涉及到Qt的一些事件处理与自定义控件.但源码好像是c++. 2.aidl跨进程调 ...

  6. SnapdragonCamera源码分析

    SnapdragonCamera源码分析 原文:https://blog.csdn.net/qingsheng33/article/details/84401223 SnapdragonCamera是 ...

  7. SnapdragonCamera源码分析(二)OpenCamera流程

    记录一下SnapdragonCamera的相关流程. 从上一篇 SnapdragonCamera源码分析(一)CameraActivity可以知道,桌面点击相机图标实质上启动的是CameraActiv ...

  8. 【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析

    目录[阅读时间:约10分钟] 一.概述 二.对比: gorilla/mux与net/http DefaultServeMux 三.简单使用 四.源码简析 1.NewRouter函数 2.HandleF ...

  9. SpringBoot-web开发(四): SpringMVC的拓展、接管(源码分析)

    [SpringBoot-web系列]前文: SpringBoot-web开发(一): 静态资源的导入(源码分析) SpringBoot-web开发(二): 页面和图标定制(源码分析) SpringBo ...

最新文章

  1. 前后端分离的探索(二)
  2. concat mysql sql注入_sql注入-mysql注入基础及常用注入语句
  3. OSNIT信息收集分析框架OSRFramework
  4. meanpool maxpool 前向和反向传播
  5. yshon对讲机如何调频率_99%的人都不知道对讲机的这些功能.....
  6. 实用python技巧
  7. python第二章上机实践_第二章上机实践报告
  8. Codevs 2756 树上的路径
  9. Referenced file contains errors (http://JAVA.sun.com/xml/ns/j2ee/web-app_2_5.xsd).
  10. 微信表情图像代表什么意思_电表型号怎么选 型号字母都代表什么意思
  11. 如何在Mac上创建和移除替身
  12. cisco5525防火墙***流量分离即***和nat并存的配置方式
  13. JavaWeb项目的热部署配置
  14. 路由器设置显示服务器拒绝访问,路由器设置服务器拒绝访问
  15. 1.计算机网络的发展,计算机网络的发展史「简述」
  16. c# 财务报表数字转大写的方法
  17. 人工智能行业每日必读(2020年1月14日)
  18. FFA 2021 专场解读 - 平台建设
  19. 【资源汇总】OpenGL
  20. 傅里叶变换-平稳信号

热门文章

  1. 机器学习SVM算法原理
  2. 阿里巴巴技术团队博客
  3. 小白的数字电路逻辑设计笔记(一)----绪论
  4. 高频覆铜板具有高技术壁垒,我国部分产品已达到世界先进水平
  5. Flutter Web 在《一起漫部》的性能优化探索与实践
  6. Ubuntu系统安装中文输入法教程
  7. ArcGIS 实验理论基础十四 空间数据库的建立
  8. 世界随机迷宫:客户端需求整理
  9. ZigBee协议简介(一)
  10. android camera 预览 数据流,camera,SurfaceView实时预览获取帧数据,在手机上总是闪退...