引子SurfaceView 是Android中较为特殊的视图,它继承自View,但与View不同的是它用于单独的绘画图层,平行与当前Activity的独立绘画图层,且它的图层在层次排列上在Activity图层的下面,因此需要在Activity图层上限时一块透明的区域,用于显示SurfaceView图层,所以其本质是SurfaceView本身任然为Activity其上的一个透明子View,只是SurfaceView中有一个Surface对象用于绘制一个平行与当前Activity且处于surfaceView之下的图层 。Surface相较于Acitivity图层的不同在于,Activity图层之上的每一个View的绘制都会导致Activity的重绘,View通过刷新来重绘视图,Android系统通过发出VSYNC信号来进行屏幕的重绘,刷新的时间间隔一般为16ms,在一些需要频繁刷新的界面,如果刷新执行很多逻辑绘制操作,就会导致刷新使用时间超过了16ms,就会导致丢帧或者卡顿,比如你更新画面的时间过长,那么你的主UI线程会被你的绘制函数阻塞,那么将无法响应按键,触屏等消息,会造成 ANR 问题 。而与View不同SurfaceView的绘制方式效率非常高,因为SurfaceView的窗口刷新的时候不需要重绘应用程序的窗口,SurfaceView拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面,由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行行绘制,由于不占用主线程资源,使得它可以实现大多复杂而高效的界面绘制,如视频播放 VideoView 和OpenGl es的 GLSurfaceView 。

文章插图
SurfaceView的特点
- SurfaceView属于被动绘制
当SurfaceView为可见状态下调用surfaceCreated(),创建其内的Surface图层,并可以进行绘制的初始化操作 。当surfaceView为隐藏状态(不可见)当前surface会被销毁 。属于被动调用,但并不是说不能主动绘制,一般的,在SurfaceHolder.Callback的surfaceCreated与surfaceDestroyed之间都是可以正常进行绘制的 。 - SurfaceView 可在任意线程进行绘制
与一般的View必须在主线程中绘制不同,SurfaceView由于其特有的单独图层的特性让其可以在任意线程中绘制,可以减少对主线程资源的持有和完成大多比较平凡耗时的绘制工作 。 - SurfaceVie使用双缓冲机制
双缓冲即在内存中创建一个与屏幕绘图区域一致的对象,先将图形绘制到内存中的这个对象上,再一次性将这个对象上的图形拷贝到屏幕上,这样能大大加快绘图的速度 。在图形图像处理编程过程中,双缓冲是一种基本的技术 。在Android中当要绘制的数据量比较大,绘图时间比较长时,重复绘图会出现闪烁现象,引起闪烁现象的主要原因是视觉反差比较大,使用双缓冲技术可以有效解决这个问题 。
package cn.enjoytoday.shortvideo.test.ui.customsurfaceimport android.content.Contextimport android.graphics.*import android.util.AttributeSetimport android.view.SurfaceHolderimport android.view.SurfaceHolder.SURFACE_TYPE_NORMALimport android.view.SurfaceViewimport java.lang.Exception/** * 作者:hfcai * 时间:19-4-22 * 博客:http://www.enjoytoday.cn * 描述:自定义SurfaceView */ class CustomerSurfaceView(context: Context, attributes: AttributeSet?, defStyleAttr:Int):SurfaceView(context,attributes,defStyleAttr), SurfaceHolder.Callback {var mIsDrawing = falsevar x =1var y = 0;private var mPath:Path?=nullprivate var mPaint: Paint?=nullvar mCanvas:Canvas?=null/*** 图层改变,当Surface的状态(大小和格式)发生变化的时候会调用该函数,在surfaceCreated调用后该函数至少会被调用一次*/override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {}/*** 图层销毁,surfaceView隐藏前surface会被销毁*/override fun surfaceDestroyed(holder: SurfaceHolder?) {mIsDrawing =false}/*** 图层创建,surfaceView可见时surface会被创建* 创建后可以开始绘制surface界面**/override fun surfaceCreated(holder: SurfaceHolder?) {holder?.let {mIsDrawing =trueSinThread().start() //mCanvas =it.lockCanvas() //lockCanvas锁定整个画布,不缓存绘制,同步线程锁 //mCanvas =it.lockCanvas(Rect(0,0,200,200)) //锁定指定位置画布,指定范围外的画布不重新绘制(缓存) ////解除线程锁,并提交绘制显示图像 //it.unlockCanvasAndPost(mCanvas)}}/*** 构造方法*/constructor(context: Context, attributes: AttributeSet?):this(context,attributes,-1)constructor(context: Context):this(context,null)init {//初始化操作holder.addCallback(this)isFocusable = trueisFocusableInTouchMode = truekeepScreenOn = true}/*** 刷新绘制*/fun refreshSin(){SinThread().start()}fun cos(){CosThread().start()}/*** 正弦函数*/inner class SinThread :Thread(){override fun run() {x =1y=0mPaint = Paint()mPaint?.strokeWidth=12fmPaint?.color = Color.BLUEmPath = Path()while (mIsDrawing) {try {mCanvas = holder.lockCanvas()mCanvas?.drawColor(Color.WHITE)mCanvas?.drawPath(mPath, mPaint)} catch (e: Exception) {e.printStackTrace()} finally {if (mCanvas != null) {holder?.unlockCanvasAndPost(mCanvas)}}x+=1if (x
- 真三A兵技巧 真三3攻略
- 遥远时空中3存档 遥远时空中3攻略
- 抖音2023好物年货节玩法攻略
- 拼多多开店攻略是什么?怎么营销?
- 暗黑血统1战神版攻略 暗黑血统攻略1
- 街机三国志攻略 街机三国攻略大全
- 龙之力攻略 龙之力量一攻略
- 设计师色彩基础攻略!快恶补一下
- 无主之地2六大角色技能 无主之地2攻略新手
- 冰封王座炉石冒险攻略 冰封王座冒险模式攻略大全
特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
