标签:更新 调用 ace 线程 图形 view aced 场景 mvc
SurfaceView 的优点
- 使用双缓冲技术
- 自带画布,支持在子线程中更新画布内容
View 和 SurfaceView 各自使用场景
- 界面需要被动更新:使用View 。 画面更新是依赖于onTouch 来完成的,所以可以直接使用 invalidate() 函数。这种情况下,两次onTouch()间隔时间较长,不会产生影响
- 界面需要主动更新:使用SurfaceView。如一个动画需要一直移动或变化,这时需要一个单独的线程不停绘制人的状态,避免阻塞主线程。
- 界面需要频繁刷新,或刷新时数据处理量较大:使用SurfaceView。如视频播放、camera
SurfaceView继承于View,因此SurfaceView 可使用View中的所有方法,但::由于View中所有方法在主线程完成,当SurfaceView重写View的方法,那么也在主线程中完成。
总结:
- 原本能通过派生自View实现的控件,依然可以通过SurfaceView 实现,因为SurfaceView派生自View
- 当SurfaceView需要使用View的onDraw()来重绘控件时,需要在初始化的时候调用setWillNotDraw(false)【surfaceview默认为true,也就是不推荐这样】,否则onDraw()函数不会被调用
- View中的所有方法都在主线程中执行,不建议使用surfaceview重写view的onDraw()函数实现自定义控件,而使用surfaceview特有的双缓冲机制绘图。
https://blog.csdn.net/u013872857/article/details/91650236 多指画图。
使用缓存Canvas绘图:
SurfaceView 初衷为:绘图操作在子线程执行, 这样就不会占用主线程的资源。
监听Surface的生命周期:
SurfaceView相关的三个概念:Surface 、SurfaceView、SurfaceHolder,这三个概念为MVC模式(Model - View - Controller)。
- Model为数据层 对应 Surface : 保存着缓冲画布与绘图内容相关的各种信息。
- View为视图层 对应 SurfaceView:代表用户交互界面,负责将Surface中存储的数据展示在View上
- Controller 为控制器,对应 SurfaceHolder : Surface中是不允许直接用来操作的,必须通过SurfaceHolder来操作Surface中的数据。
由于canvas被保存在Surface中的,那么,必须Surface存在的时候,才能操作缓存Canvas,否则容易导致获取到的Canvas为空。因此我们可以在SurfaceHolder中添加对Surface生命周期的监听。
以下为监听的三个函数:
- SurfaceCreated() : 当Surface对象被创建后,该函数将立即被调用
- nSurfaceChange() : 当Surface发生任何结构性变化,该函数将立即被调用
- SurfaceDestroy() : 当Surface对象将要销毁时,该函数将立即被调用
- 通常 在SurfaceCrrated中开启线程来操作,防止Surface还未创建 , 调用SurfaceDestroyed 看线程是否执行完,未执行完则强制取消。
双缓冲技术为至少两块画布,使用lockCanvas()时对画布进行操作,使用unlockCanvasAndPost()时替换画布,并开始呈现刚刚对画布的操作。
- lockCanvas() : 用于获取整屏画布
- lockCanvas(Rect dirty): 用于获取指定区域的画布
surfaceView 如果默认为三块画布:
- 画布1展示 , 画布2,3缓冲, 此时画布1被清屏(全部绘制成黑色)
- 画布2与画布1换位子,画布2先复制画布1,再将自己的图形覆盖上去
- 画布3与画布2换位子,画布3先复制画布2,再将自己的图形覆盖上去
小总结:
- 缓冲画布是按照LRU(先进先出)策略被存取使用的
- 用holder.lockCanvas(rect) 获取到画布区域,再通过unlockCanvasAndPost(Canvas)函数提交到屏幕上, 指定区域内的内容为我们叠加(新的在上)绘制的结果,区域外是从当前屏幕复制过来的。
- 为防止区域内与区域外的图像所产生的内容有冲突,建议先清空画布。 只有我们将每块画布都画过以后,系统才会按照我们指定的区域来返回画布大小
- 如果不是区域绘制,仅仅是绘制数字那种,则不会复制前一块画布的内容,只展示自己画布的内容,因此出现1,3,5,7,9 而不是0,1,2,3,。。。。可以采用一个数组将其保存,然后每次画都逐个遍历
总结:
- 缓冲画布存取遵循LRU 策略
- lockCanvas() 获得整个画布,lockCanvas(dirt rect) 获取指定大小的缓冲画布
- 使用lockCanvas(rect) 函数获取缓冲画布前,需要使用while清屏 画布未清空前,第一次拿到的画布将为整屏。
- 所获得画布以内的区域仍在原缓冲画布上叠加作画, 画布以外区域从屏幕上直接复制过来
- 由于画布以内的区域是原缓冲画布的基础上叠加作画,防止冲突,可使用Xfermode先清空所获得的的画布;或在内容不交叉时,采用增量绘制。
surfaceview
标签:更新 调用 ace 线程 图形 view aced 场景 mvc
原文地址:https://www.cnblogs.com/acg88688/p/11870588.html