Android游戏编程之SurfaceView进行连续渲染
来源:互联网 发布:看图软件 安卓版 编辑:程序博客网 时间:2024/06/05 09:28
以下均转自Android游戏编程入门经典,转载请标明出处
SurfaceView类是一个用于处理Surface的视图,也是Android API提供的另一个类。
什么是Surface?它是一个抽象的原是缓冲区,被屏幕组合器用于渲染特定视图。屏幕组合器是Android上所有渲染的幕后推手,并最终负责将所有的像素点推送到GPU。
我们的目标就是在一个独立的线程中执行渲染,而不用大量占用UI线程,因为UI线程还有很多工作要做。SurfaceView类提供了一种在UI线程之外的线程中进行渲染的方式。
SurfaceHolder和锁定
为了在UI线程之外的另一个不同线程中渲染到SurfaceView,我们需要获得一个SurfaceHolder类的实例,如下所示:
SurfaceHolder holder = surfaceView.getHolder();
SurfaceHolder是Surface的一个包装,可为我们做一些辅助工作。它提供两个方法:
Canvas SurfaceHolder.lockCanvas();
SurfaceHolder.unlockAndPost(Canvas canvas);
第一个方法锁定Surface用于渲染并返回一个可用的Canvas实例。第二个方法解锁Surface并确保通过Canvas进行绘制的内容可显示在屏幕上。我们将在渲染线程中使用这两个方法以获取Canvas,通过它进行渲染并最终确保我们渲染的图像能在屏幕上可见。我们必须确保传递到SurfaceHolder.unlockAndPost()方法的Canvas与从SurfaceHolder.lockCanvas()方法接收的相同。
当SurfaceView被实例化时,Surface并没有立即创建。相反,它是异步创建的。每当活动暂停或再次恢复而重新创建时,该Surface都将被销毁。
Surface的创建与有效性
只要Surface没有生效,我们就不能从SurfaceHolder中获取Canvas。不过,我们可以通过下面的语句来查看Surface是否已被创建:
boolean isCreated = surfaceHolder.getSurface().isValid();
如果该方法返回true,我们就可安全的锁定该Surface并通过接收到的Canvas来在其上进行绘制。我们必须绝对确保在调用SurfaceHolder.lockCanvas()之后再次解锁Surface,否则我们的活动可能会锁定手机。
综合运用
下面看一个实例,其中使用SurfaceHolder在一个单独线程中执行渲染。
package org.example.ch04_android_basics;import java.util.Random;import android.app.Activity;import android.content.Context;import android.graphics.Canvas;import android.os.Bundle;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.Window;import android.view.WindowManager;public class SurfaceViewTest extends Activity {FastRenderView renderView;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);renderView = new FastRenderView(this);setContentView(renderView);}@Overrideprotected void onPause() {// TODO Auto-generated method stubsuper.onPause();renderView.pause();}@Overrideprotected void onResume() {// TODO Auto-generated method stubsuper.onResume();renderView.resume();}class FastRenderView extends SurfaceView implements Runnable{Thread renderThread = null;SurfaceHolder holder;Random rand = new Random();volatile boolean running = false;public FastRenderView(Context context) {super(context);// TODO Auto-generated constructor stubholder = getHolder();}public void resume(){running = true;renderThread = new Thread(this);renderThread.start();}public void run(){while(running){if(!holder.getSurface().isValid())continue;Canvas canvas = holder.lockCanvas();canvas.drawRGB(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255));holder.unlockCanvasAndPost(canvas);}}public void pause(){running = false;while(true){try{renderThread.join();break;}catch(InterruptedException e){// retry}}}}}
在onCreate()方法中,我们启动了全屏幕模式,创建FastRenderView实例并将其设置为活动的内容视图。
这次我们重写了onResume()方法。在该方法中,我们通过调用FastRenderView.resume()方法间接启动渲染线程,该方法将在内部处理所有操作。这就意味着该线程在活动创建时就启动(在执行onCreate()之后总是会调用onResume()方法)。当该活动从暂停状态恢复时,也将重新启动该线程。
当然,这也意味着我们必须在某个地方停止该线程;否则,我们需要在每次调用onResume()方法时创建一个新的线程。应该在onPause()方法内执行该操作。当调用FastRenderView.pause()方法时,将会完全停止该线程。该方法在线程完全停止之前不会返回。
在这里running标志的volatile修饰符,为什么需要它?原因很微妙:当编译器知道在方法的第一行与while块之间没有依赖关系时,它将会决定在FastRenderView.pause()方法中重新排序语句。只要它认为这样做能加快代码执行速度,它就允许这样做。不过,我们还是依赖在该方法中指定的顺序。试想一下,如果我们试图连接线程之后设置running标志会怎么样。我们将会进入一个无限的循环,并且线程永远无法终止。
volatile修饰符就是为了防止这种情况发生,任何引用改成员的语句都将按顺序执行。这就避免了我们处理一个没有能力进行完全再现的BUG。
在我们从活动的onPause()方法返回后,Surface将总是被销毁。因为我们通过FastRenderView.pause()方法进行等待直到线程销毁,当Surface被真正销毁之后,渲染线程将不可能存活。
运行效果:
运行效果应该说屏幕显示的是一种随机颜色,但是手机一直在闪着不同颜色,手机接下的图片就变成这样了
- Android游戏编程之SurfaceView进行连续渲染
- android游戏之SurfaceView
- Android 游戏开发之 SurfaceView
- 【读书笔记《Android游戏编程之从零开始》】11.游戏开发基础(SurfaceView 游戏框架、View 和 SurfaceView 的区别)
- SurfaceView 连续渲染 SurfaceHolder Canvas
- Android游戏开发之SurfaceView动画
- Android 游戏开发之SurfaceView框架
- android游戏开发初学之SurfaceView创建
- Android游戏开发之SurfaceView与游戏开发
- android 游戏框架SurfaceView
- android 游戏 SurfaceView 未完成
- 【读书笔记《Android游戏编程之从零开始》】14.游戏开发基础(Bitmap 位图的渲染与操作)
- Android游戏开发之旅(二)View和SurfaceView
- Android游戏开发之旅(七)自定义SurfaceView
- Android游戏开发之旅(八)SurfaceView类实例
- 【Android游戏开发之三】剖析 SurfaceView ! Callback以及SurfaceHolder!!
- Android游戏开发之旅二 View和SurfaceView
- Android游戏开发之旅七 自定义SurfaceView
- 从朋友的签名上看来的,觉得很有意义……“三帮三不帮原则”
- “坑爹的LIST容器--删除操作千倍消耗CPU”一文有误,在VC2010里是STL完胜
- 玩具语言LLL之Lex
- UVA 10382 Watering Grass(区间嵌套)
- 第六章 表达式
- Android游戏编程之SurfaceView进行连续渲染
- HDU_2026 首写字母变大写
- 第七章 方法
- Oracle锁机制
- A Lightweight Logger for C++
- Linux -> Linux下的Python脚本编程
- 操作系统选择成固定模式 HTML5是潜在方向
- 中国联通WCDMA网编号计划和频率及扰码规划
- 结构型模式: Proxy(代理)