我正在尝试制作一个简单的飞机游戏来培养我的技能并获得一些乐趣。但是当我试图从一个TextView
到 Thread
绘制我的飞机。我将尝试仅包含下面的基本代码,并使用“...”来指示省略的行。
我正在一个单独的、优秀的老式 android 线程中绘图。下面是 Thread
的构造函数:
public class BenThread extends Thread {
...
public BenThread(SurfaceHolder surfaceHolder, Context context,
BenSurfaceView surfaceView) {
this.surfaceHolder = surfaceHolder;
this.context = context;
this.surfaceView = surfaceView;
this.isRunning = false;
Bitmap planeImage = BitmapFactory.decodeResource(
context.getResources(), R.drawable.fighters);
airplane = new Airplane(50, 50, 2, 0, planeImage);
}
在我展示 run 方法之前,请注意有一个 SurfaceView
在调用 SurfaceChanged()
时创建并启动 Thread
。在我的主要 Activity
的 onCreate()
中,我创建了自定义 SurfaceView
的最终实例:
final BenSurfaceView surfaceView = (BenSurfaceView) findViewById(R.id.surfaceView);
在 UI 布局中,有一个 TextView
位于底部中央,并连接了一个 OnTouchListener
。在 onTouch()
中,对于 MotionEvent.ACTION_DOWN
,调用以下行:
surfaceView.thread.handler.sendEmptyMessage(1);
回到线程类,这个空消息的处理程序是在 run 方法中创建的,同时创建了 Looper
:
public void run() {
super.run();
Looper.prepare(); // Creates a Message Queue for the thread
MessageQueue queue = Looper.myQueue();
queue.addIdleHandler(new IdleHandler() {
@Override
public boolean queueIdle() {
Looper.myLooper().quit();
return false;
}
});
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
Log.i("HANDLING", "SOMETHING");
}
};
Looper.loop();
while (isRunning) {
currentTime = System.currentTimeMillis();
// spin in a while loop for a while
while ((currentTime - previousTime) < REFRESH_RATE) {
currentTime = System.currentTimeMillis();
}
airplane.move();
canvas = surfaceHolder.lockCanvas();
if (canvas != null) {
surfaceView.draw(canvas);
airplane.draw(canvas);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
现在,如果我按原样运行,我会看到飞机在屏幕上移动的漂亮小动画。
但是,当我单击底部的 Button
时,我从日志中看到我向死线程发送了一条消息。好吧,我想我在 IdleHandler
中杀死了它。所以现在让我注释掉 quit 方法:
// Looper.myLooper().quit();
现在我的应用程序看起来不那么令人兴奋了:
但是,当我点击底部的按钮
并查看日志时,有证据表明我的消息已被处理!所以最大的问题是,我怎样才能运行消息循环并仍然看到我的动画?
最佳答案
调用 Looper.loop()
后,它不应返回,直到线程准备好停止。让您的游戏在 Looper.loop()
调用之后 循环没有意义。在那一点上,线程“死了”,因为 Looper 不再监听消息。
如果您希望您的线程在 while (isRunning)
中运行,请执行此操作。如果您希望它是消息驱动的,请执行此操作。不要试图在同一个线程中同时执行这两项操作。 (请不要在 CPU 上旋转——在移动设备上会很快耗尽电池电量。)
您可以在 this article 的附录 A 和 B 中找到有关游戏循环、SurfaceView 和线程的一些说明。 . Grafika 中有各种使用 Handler 进行动画渲染的示例.例如,“记录 GL 应用程序” Activity 使用 Choreographer 在需要绘制时向渲染线程发送消息。
关于java - 如何在绘图线程中使用Android的Looper,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24333878/