布吉网站建设哪家公司便宜点,企业是做app还是做网站,个人备案的网站内容,wordpress加ssl1. SurfaceView介绍 通常情况程序的View和用户响应都是在同一个线程中处理的#xff0c;这也是为什么处理长时间事件#xff08;例如访问网络#xff09;需要放到另外的线程中去#xff08;防止阻塞当前UI线程的操作和绘制#xff09;。但是在其他线程中却不能修改UI元素这也是为什么处理长时间事件例如访问网络需要放到另外的线程中去防止阻塞当前UI线程的操作和绘制。但是在其他线程中却不能修改UI元素例如用后台线程更新自定义View调用View的在自定义View中的onDraw函数是不允许的。 如果需要在另外的线程绘制界面、需要迅速的更新界面或者渲染UI界面需要较长的时间这种情况就要使用SurfaceView了。SurfaceView中包含一个Surface对象而Surface是可以在后台线程中绘制的。SurfaceView的性质决定了其比较适合一些场景需要界面迅速更新、对帧率要求较高的情况。使用SurfaceView需要注意以下几点情况1SurfaceView和SurfaceHolder.Callback函数都从当前SurfaceView窗口线程中调用一般而言就是程序的主线程。2有关资源状态要注意和绘制线程之间的同步。 3在绘制线程中必须先合法的获取Surface才能开始绘制内容在SurfaceHolder.Callback.surfaceCreated() 和SurfaceHolder.Callback.surfaceDestroyed()之间的状态为合法的在Surface类型为SURFACE_TYPE_PUSH_BUFFERS时是不合法的。 4额外的绘制线程会消耗系统的资源在使用SurfaceView的时候要注意这点。 2. 使用SurfaceView 只要继承SurfaceView类并实现SurfaceHolder.Callback接口就可以实现一个自定义的SurfaceView了SurfaceHolder.Callback在底层的Surface状态发生变化的时候通知ViewSurfaceHolder.Callback具有如下的接口surfaceCreated(SurfaceHolder holder)当Surface第一次创建后会立即调用该函数。程序可以在该函数中做些和绘制界面相关的初始化工作一般情况下都是在另外的线程来绘制界面所以不要在这个函数中绘制Surface。 surfaceChanged(SurfaceHolder holder, int format, int width,int height)当Surface的状态大小和格式发生变化的时候会调用该函数在surfaceCreated调用后该函数至少会被调用一次。 surfaceDestroyed(SurfaceHolder holder)当Surface被摧毁前会调用该函数该函数被调用后就不能继续使用Surface了一般在该函数中来清理使用的资源。 通过SurfaceView的getHolder()函数可以获取SurfaceHolder对象Surface 就在SurfaceHolder对象内。虽然Surface保存了当前窗口的像素数据但是在使用过程中是不直接和Surface打交道的由SurfaceHolder的Canvas.lockCanvas()或则Canvas.lockCanvas(Rect dirty)函数来获取Canvas对象通过在Canvas上绘制内容来修改Surface中的数据。如果Surface不可编辑或者尚未创建调用该函数会返回null在 unlockCanvas() 和 lockCanvas()中Surface的内容是不缓存的所以需要完全重绘Surface的内容为了提高效率只重绘变化的部分则可以调用lockCanvas(Rect dirty)函数来指定一个dirty区域这样该区域外的内容会缓存起来。在调用lockCanvas函数获取Canvas后SurfaceView会获取Surface的一个同步锁直到调用unlockCanvasAndPost(Canvas canvas)函数才释放该锁这里的同步机制保证在Surface绘制过程中不会被改变被摧毁、修改。当在Canvas中绘制完成后调用函数unlockCanvasAndPost(Canvas canvas)来通知系统Surface已经绘制完成这样系统会把绘制完的内容显示出来。为了充分利用不同平台的资源发挥平台的最优效果可以通过SurfaceHolder的setType函数来设置绘制的类型目前接收如下的参数SURFACE_TYPE_NORMAL用RAM缓存原生数据的普通Surface SURFACE_TYPE_HARDWARE适用于DMA(Direct memory access )引擎和硬件加速的Surface SURFACE_TYPE_GPU适用于GPU加速的Surface SURFACE_TYPE_PUSH_BUFFERS表明该Surface不包含原生数据Surface用到的数据由其他对象提供在Camera图像预览中就使用该类型的Surface有Camera负责提供给预览Surface数据这样图像预览会比较流畅。如果设置这种类型则就不能调用lockCanvas来获取Canvas对象了。注意一个SurfaceView只在SurfaceHolder.Callback.surfaceCreated() 和 SurfaceHolder.Callback.surfaceDestroyed()调用之间是可用的其他时间是得不到它的Canvas对象的null。 3. SurfaceView和View的区别 SurfaceView和View最本质的区别在于surfaceView是在一个新起的单独线程中可以重新绘制画面而View必须在UI的主线程中更新画面。 在UI的主线程中更新画面可能会引发问题比如你更新画面的时间过长那么你的主UI线程会被你正在画的函数阻塞。那么将无法响应按键触屏等消息。当使用SurfaceView时由于是在新的线程中更新画面所以不会阻塞UI主线程。但这也带来了另外一个问题就是事件同步。比如你触屏了一下你需要SurfaceView中的Thread处理一般就需要有一个event queue的设计来保存touch event这会稍稍复杂一点因为涉及到线程同步。 所以基于以上根据游戏特点一般分成两类 1被动更新画面的。比如棋类用View就好了。因为画面的更新是依赖于 onTouch 来更新可以直接使用 invalidate。 因为在这种情况下这一次Touch和下一次的Touch需要的时间比较长些不会产生影响。 2主动更新画面的。比如一个人在一直跑动。这就需要一个单独的thread不停的重绘人的状态避免阻塞UI主线程。所以显然view不合适需要surfaceView来控制。