)
我有一个onCreate方法,如下所示:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
boolean isLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
int frameBufferWidth = isLandscape ? 480 : 320;
int frameBufferHeight = isLandscape ? 320 : 480;
Bitmap frameBuffer = Bitmap.createBitmap(frameBufferWidth,
frameBufferHeight, Config.RGB_565);
float scaleX = (float) frameBufferWidth
/ getWindowManager().getDefaultDisplay().getWidth();
float scaleY = (float) frameBufferHeight
/ getWindowManager().getDefaultDisplay().getHeight();
renderView = new AndroidFastRenderView(this, frameBuffer);
graphics = new AndroidGraphics(getAssets(), frameBuffer);
fileIO = new AndroidFileIO(this);
audio = new AndroidAudio(this);
input = new AndroidInput(this, renderView, scaleX, scaleY);
screen = getStartScreen();
setContentView(renderView);
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "GLGame");
}
有趣的是:
renderView = new AndroidFastRenderView(this, frameBuffer);
AndroidFastRenderView类的代码(this,frameBuffer):
public class AndroidFastRenderView extends SurfaceView implements Runnable {
AndroidGame game;
Bitmap framebuffer;
Thread renderThread = null;
SurfaceHolder holder;
volatile boolean running = false;
public AndroidFastRenderView(AndroidGame game, Bitmap framebuffer) {
super(game);
this.game = game;
this.framebuffer = framebuffer;
this.holder = getHolder();
}
public void resume() {
running = true;
renderThread = new Thread(this);
renderThread.start();
}
public void run() {
Rect dstRect = new Rect();
long startTime = System.nanoTime();
while(running) {
if(!holder.getSurface().isValid())
continue;
float deltaTime = (System.nanoTime()-startTime) / 1000000000.0f;
startTime = System.nanoTime();
game.getCurrentScreen().update(deltaTime);
game.getCurrentScreen().present(deltaTime);
Canvas canvas = holder.lockCanvas();
canvas.getClipBounds(dstRect);
canvas.drawBitmap(framebuffer, null, dstRect, null);
holder.unlockCanvasAndPost(canvas);
}
}
public void pause() {
running = false;
while(true) {
try {
renderThread.join();
return;
} catch (InterruptedException e) {
// retry
}
}
}
}
稍后在我的Activity中有一个onResume方法,它在onCreate之后执行:
@Override
public void onResume() {
super.onResume();
wakeLock.acquire();
screen.resume();
renderView.resume();
}
在这里你可以看到执行了renderView对象的resume方法,它创建了一个新线程(将它与AnroidFastRenderView进行比较)。
现在我的问题。新线程执行run方法包含的代码。此代码负责在显示屏上绘制内容。但我不明白将在新线程中执行什么,什么不会。这是一个可能是一个屏幕的例子:
public class MainMenuScreen extends Screen {
public MainMenuScreen(Game game) {
super(game);
}
public void update(float deltaTime) {
Graphics g = game.getGraphics();
List<TouchEvent> touchEvents = game.getInput().getTouchEvents();
game.getInput().getKeyEvents();
int len = touchEvents.size();
for(int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
if(event.type == TouchEvent.TOUCH_UP) {
if(inBounds(event, 0, g.getHeight() - 64, 64, 64)) {
Settings.soundEnabled = !Settings.soundEnabled;
if(Settings.soundEnabled)
Assets.click.play(1);
}
if(inBounds(event, 64, 220, 192, 42) ) {
game.setScreen(new GameScreen(game));
if(Settings.soundEnabled)
Assets.click.play(1);
return;
}
if(inBounds(event, 64, 220 + 42, 192, 42) ) {
game.setScreen(new HighscoreScreen(game));
if(Settings.soundEnabled)
Assets.click.play(1);
return;
}
if(inBounds(event, 64, 220 + 84, 192, 42) ) {
game.setScreen(new HelpScreen(game));
if(Settings.soundEnabled)
Assets.click.play(1);
return;
}
}
}
}
private boolean inBounds(TouchEvent event, int x, int y, int width, int height) {
if(event.x > x && event.x < x + width - 1 &&
event.y > y && event.y < y + height - 1)
return true;
else
return false;
}
public void present(float deltaTime) {
Graphics g = game.getGraphics();
g.drawPixmap(Assets.background, 0, 0);
g.drawPixmap(Assets.logo, 32, 20);
g.drawPixmap(Assets.mainMenu, 64, 220);
if(Settings.soundEnabled)
g.drawPixmap(Assets.buttons, 0, 416, 0, 0, 64, 64);
else
g.drawPixmap(Assets.buttons, 0, 416, 64, 0, 64, 64);
}
public void pause() {
Settings.save(game.getFileIO());
}
public void resume() {
}
public void dispose() {
}
}
在AnroidFastRenderView的run方法中有两个重要的行:
game.getCurrentScreen().update(deltaTime);
game.getCurrentScreen().present(deltaTime);
这两行都执行MainMenuScreen示例的更新和显示方法。在我看来,这仍将发生在同一个新线程中。所以现在发生的一切都是由新线程完成的。在activity类中的onResume方法之后,没有什么可做的,所以旧线程无关。在我看来,没有任何事情发生并行,但这实际上是另一个线程的原因。
我哪里错了?
很抱歉这个问题很长。我希望你能帮助我。
电贺 彼得
P.S。:代码来自“Beginning Android Games”一书。