Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用安卓&x27;画图线中的活套_Java_Android_Multithreading_Surfaceview - Fatal编程技术网

Java 如何使用安卓&x27;画图线中的活套

Java 如何使用安卓&x27;画图线中的活套,java,android,multithreading,surfaceview,Java,Android,Multithreading,Surfaceview,我正在尝试制作一个简单的飞机游戏来提高我的技能并获得一些乐趣。但是当我试图从onTouch事件中的TextView向绘制我的飞机的线程传递消息时,我遇到了Threads、Loopers和消息队列的障碍。我将尝试只包含下面的基本代码位,并使用“…”表示省略的行 我正在用一个单独的、好的老式安卓线程进行绘制。下面是线程的构造函数: public class BenThread extends Thread { ... public BenThread(SurfaceHolder surfaceHol

我正在尝试制作一个简单的飞机游戏来提高我的技能并获得一些乐趣。但是当我试图从
onTouch
事件中的
TextView
向绘制我的飞机的
线程传递消息时,我遇到了
Thread
s、
Looper
s和消息队列的障碍。我将尝试只包含下面的基本代码位,并使用“…”表示省略的行

我正在用一个单独的、好的老式安卓线程进行绘制。下面是
线程的构造函数

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()
时创建并启动
线程。在我的主要
活动
onCreate()
中,我创建了自定义
SurfaceView
的最终实例:

final BenSurfaceView surfaceView = (BenSurfaceView) findViewById(R.id.surfaceView);
在UI布局中,有一个
TextView
位于底部中间,一个
OnTouchListener
连接在一起。在
onTouch()
中,对于
MotionEvent.ACTION\u DOWN
,调用以下行:

surfaceView.thread.handler.sendEmptyMessage(1);
回到thread类,此空消息的处理程序将在run方法中创建,同时创建
循环器
创建:

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);
        }
    }
}
现在,我的应用程序看起来不那么令人兴奋:


但是,当我点击底部的
按钮查看日志时,有证据表明我的消息已被处理!因此,最大的问题是,如何运行消息循环并仍能看到我的动画?

在调用
Looper.loop()
之后,它应该不会返回,直到线程准备停止。在调用
Looper.loop()
之后进行游戏循环是没有意义的。此时线程处于“死”状态,即活套不再侦听消息

如果希望线程在运行(isRunning)
时在
中运行,请执行该操作。如果您希望它是消息驱动的,那么就这样做。不要试图在同一个线程中同时做这两件事。(请不要在CPU上旋转——在移动设备上会很快耗尽电池。)


您可以在的附录A和附录B中找到一些关于游戏循环、SurfaceView和线程的注释。中有使用处理程序进行动画渲染的各种示例。例如,“record GL app”活动使用Choreographer在绘图时向渲染线程发送消息。

调用
Looper.loop()
后,在线程准备停止之前,它不应返回。在调用
Looper.loop()
之后进行游戏循环是没有意义的。此时线程处于“死”状态,即活套不再侦听消息

如果希望线程在运行(isRunning)
时在
中运行,请执行该操作。如果您希望它是消息驱动的,那么就这样做。不要试图在同一个线程中同时做这两件事。(请不要在CPU上旋转——在移动设备上会很快耗尽电池。)


您可以在的附录A和附录B中找到一些关于游戏循环、SurfaceView和线程的注释。中有使用处理程序进行动画渲染的各种示例。例如,“record GL app”活动使用Choreographer在绘图时向渲染线程发送消息。

这是因为IdleHandler()。它是立即执行退出你的活套。我评论了你的代码:

public void run() {
super.run();
Looper.prepare();
MessageQueue queue = Looper.myQueue();
queue.addIdleHandler(new IdleHandler() {
    // This is executed immediately when the looper is idle.
    // So this looper is quitted
    // and thread starts to execute "while" loop
    @Override
    public boolean queueIdle() {
        Looper.myLooper().quit();
        return false;
    }
});
handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        Log.i("HANDLING", "SOMETHING");
    }
};
Looper.loop();  // Take into account that this function is blocking
// This "while" loop is executed after the looper is quitted from IdleHandler
// So why your game is running
// When you click your button it tries to send message to quitted looper
// and you get the corresponding error message
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);
    }
}
public void run(){
super.run();
Looper.prepare();
MessageQueue=Looper.myQueue();
addIdleHandler(新的IdleHandler(){
//当活套处于空闲状态时,将立即执行此操作。
//所以这个活套退出了
//线程开始执行“while”循环
@凌驾
公共布尔队列空闲(){
Looper.myLooper().quit();
返回false;
}
});
handler=newhandler(){
@凌驾
公共无效handleMessage(消息消息消息){
Log.i(“处理”、“某物”);
}
};
Looper.loop();//请考虑此函数正在阻塞
//这个“while”循环是在循环器从IdleHandler退出后执行的
//那么为什么你的游戏在运行呢
//当你点击你的按钮时,它会尝试向退出的活套发送消息
//您将得到相应的错误消息
同时(正在运行){
currentTime=System.currentTimeMillis();
//在while循环中旋转一段时间
while((currentTime-previousTime)<刷新率){
currentTime=System.currentTimeMillis();
}
飞机。移动();
canvas=surfaceHolder.lockCanvas();
if(canvas!=null){
绘制(画布);
飞机。画(画布);
surfaceHolder.unlockCanvasAndPost(画布);
}
}
}


当您注释IdleHandler时,线程执行Looper.loop()(它是阻塞的)方法,因此不会到达while循环。

这是因为IdleHandler()。它是立即执行退出你的活套。我评论了你的代码:

public void run() {
super.run();
Looper.prepare();
MessageQueue queue = Looper.myQueue();
queue.addIdleHandler(new IdleHandler() {
    // This is executed immediately when the looper is idle.
    // So this looper is quitted
    // and thread starts to execute "while" loop
    @Override
    public boolean queueIdle() {
        Looper.myLooper().quit();
        return false;
    }
});
handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        Log.i("HANDLING", "SOMETHING");
    }
};
Looper.loop();  // Take into account that this function is blocking
// This "while" loop is executed after the looper is quitted from IdleHandler
// So why your game is running
// When you click your button it tries to send message to quitted looper
// and you get the corresponding error message
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);
    }
}
public void run(){
super.run();
Looper.prepare();
MessageQueue=Looper.myQueue();
addIdleHandler(新的IdleHandler(){
//当活套处于空闲状态时,将立即执行此操作。
//所以这个活套退出了
//线程开始执行“while”循环
@凌驾
公共布尔队列空闲(){
Looper.myLooper().quit();
返回false;
}
});
handler=newhandler(){
@凌驾
公共无效handleMessage(消息消息消息){
Log.i(“处理”、“某物”);
}
};
Looper.loop();//请考虑此函数正在阻塞
//这个“while”循环是在循环器从IdleHandler退出后执行的
//那么为什么你的游戏在运行呢
//当你点击你的按钮时,它会尝试向退出的活套发送消息
//您将得到相应的错误消息
同时(正在运行){
currentTime=System.currentTimeMillis();
//在while循环中旋转一段时间
while((currentTime-previousTime)<刷新率){
currentTime=System.currentTimeMillis();
}
飞机。移动();
canvas=surfaceHolder.lo
surfaceView.thread.handler.sendEmptyMessage(1);
surfaceView.thread.airplane.setVelocity(8);
@Override
public void run(){
    while (isRunning) {
        airplane.move();
        canvas = surfaceHolder.lockCanvas();
        if (canvas != null) {
            surfaceView.draw(canvas);
            airplane.draw(canvas);
            surfaceHolder.unlockCanvasAndPost(canvas);
        }
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}