zoukankan      html  css  js  c++  java
  • surfaceview

    SurfaceView 的优点

    1. 使用双缓冲技术
    2. 自带画布,支持在子线程中更新画布内容

    View 和 SurfaceView 各自使用场景

    1. 界面需要被动更新:使用View 。 画面更新是依赖于onTouch 来完成的,所以可以直接使用 invalidate() 函数。这种情况下,两次onTouch()间隔时间较长,不会产生影响
    2. 界面需要主动更新:使用SurfaceView。如一个动画需要一直移动或变化,这时需要一个单独的线程不停绘制人的状态,避免阻塞主线程。
    3. 界面需要频繁刷新,或刷新时数据处理量较大:使用SurfaceView。如视频播放、camera

    SurfaceView继承于View,因此SurfaceView 可使用View中的所有方法,但::由于View中所有方法在主线程完成,当SurfaceView重写View的方法,那么也在主线程中完成。

    总结:

    1. 原本能通过派生自View实现的控件,依然可以通过SurfaceView 实现,因为SurfaceView派生自View
    2. 当SurfaceView需要使用View的onDraw()来重绘控件时,需要在初始化的时候调用setWillNotDraw(false)【surfaceview默认为true,也就是不推荐这样】,否则onDraw()函数不会被调用
    3. View中的所有方法都在主线程中执行,不建议使用surfaceview重写view的onDraw()函数实现自定义控件,而使用surfaceview特有的双缓冲机制绘图。

    https://blog.csdn.net/u013872857/article/details/91650236 多指画图。

    使用缓存Canvas绘图:

    SurfaceView 初衷为:绘图操作在子线程执行, 这样就不会占用主线程的资源。

    监听Surface的生命周期:

    SurfaceView相关的三个概念:Surface 、SurfaceView、SurfaceHolder,这三个概念为MVC模式(Model - View - Controller)。

    1. Model为数据层 对应 Surface :       保存着缓冲画布与绘图内容相关的各种信息。
    2. View为视图层   对应 SurfaceView:代表用户交互界面,负责将Surface中存储的数据展示在View上
    3. Controller 为控制器,对应 SurfaceHolder : Surface中是不允许直接用来操作的,必须通过SurfaceHolder来操作Surface中的数据。

    由于canvas被保存在Surface中的,那么,必须Surface存在的时候,才能操作缓存Canvas,否则容易导致获取到的Canvas为空。因此我们可以在SurfaceHolder中添加对Surface生命周期的监听。

    以下为监听的三个函数:

    1. SurfaceCreated() : 当Surface对象被创建后,该函数将立即被调用
    2. nSurfaceChange() : 当Surface发生任何结构性变化,该函数将立即被调用
    3. SurfaceDestroy() : 当Surface对象将要销毁时,该函数将立即被调用
    4. 通常       在SurfaceCrrated中开启线程来操作,防止Surface还未创建     ,    调用SurfaceDestroyed 看线程是否执行完,未执行完则强制取消。

    双缓冲技术为至少两块画布,使用lockCanvas()时对画布进行操作,使用unlockCanvasAndPost()时替换画布,并开始呈现刚刚对画布的操作。

    1. lockCanvas() :                   用于获取整屏画布
    2. lockCanvas(Rect dirty):   用于获取指定区域的画布

    surfaceView 如果默认为三块画布:

    1. 画布1展示 , 画布2,3缓冲, 此时画布1被清屏(全部绘制成黑色)
    2. 画布2与画布1换位子,画布2先复制画布1,再将自己的图形覆盖上去
    3. 画布3与画布2换位子,画布3先复制画布2,再将自己的图形覆盖上去

    小总结:

    1. 缓冲画布是按照LRU(先进先出)策略被存取使用的
    2. 用holder.lockCanvas(rect) 获取到画布区域,再通过unlockCanvasAndPost(Canvas)函数提交到屏幕上, 指定区域内的内容为我们叠加(新的在上)绘制的结果,区域外是从当前屏幕复制过来的。
    3. 为防止区域内与区域外的图像所产生的内容有冲突,建议先清空画布。         只有我们将每块画布都画过以后,系统才会按照我们指定的区域来返回画布大小
    4. 如果不是区域绘制,仅仅是绘制数字那种,则不会复制前一块画布的内容,只展示自己画布的内容,因此出现1,3,5,7,9 而不是0,1,2,3,。。。。可以采用一个数组将其保存,然后每次画都逐个遍历

    总结:

    1. 缓冲画布存取遵循LRU 策略
    2. lockCanvas() 获得整个画布,lockCanvas(dirt rect) 获取指定大小的缓冲画布
    3. 使用lockCanvas(rect) 函数获取缓冲画布前,需要使用while清屏                                                       画布未清空前,第一次拿到的画布将为整屏。
    4. 所获得画布以内的区域仍在原缓冲画布上叠加作画, 画布以外区域从屏幕上直接复制过来
    5. 由于画布以内的区域是原缓冲画布的基础上叠加作画,防止冲突,可使用Xfermode先清空所获得的的画布;或在内容不交叉时,采用增量绘制。
  • 相关阅读:
    项目中常用的linux命令
    Flutter移动电商实战 --(12)首页导航区域编写
    Flutter移动电商实战 --(13)ADBanner组件的编写
    Flutter移动电商实战 --(10)使用FlutterSwiper制作轮播效果
    Flutter移动电商实战 --(9)移动商城数据请求实战
    Flutter移动电商实战 --(8)dio基础_伪造请求头获取数据
    Flutter移动电商实战 --(7)dio基础_POST请求的使用
    Flutter移动电商实战 --(6)dio基础_Get_Post请求和动态组件协作
    Flutter移动电商实战 --(5)dio基础_引入和简单的Get请求
    Flutter移动电商实战 --(4)打通底部导航栏
  • 原文地址:https://www.cnblogs.com/acg88688/p/11870588.html
Copyright © 2011-2022 走看看