当我显示Game Over Dialog时,我收到错误“无法在线程内创建处理程序未调用Looper.prepare()”

时间:2012-03-27 12:01:20

标签: android alertdialog ui-thread

我正在为Android编写一款小游戏。游戏使用Thread在SurfaceView上绘制。在Thread的run()方法中,我测试游戏是否结束,如果是,我尝试在对话框上显示游戏,但这给了我前面提到的错误信息。 我知道当非UI线程试图弄乱UI时会发生此错误。我想知道的是显示这种对话的最佳方法。我已粘贴下面的代码。 谢谢你的帮助:

public class BouncingBallActivity extends Activity{

    private static final int DIALOG_GAMEOVER_ID = 0;
    private BouncingBallView bouncingBallView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bouncingBallView = new BouncingBallView(this);
        bouncingBallView.resume();
        setContentView(bouncingBallView);
    }

    protected Dialog onCreateDialog(int id)
    {
        switch (id) {
        case DIALOG_GAMEOVER_ID:
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setMessage("Game Over.")
                    .setCancelable(false)
                    .setPositiveButton("Try Again",
                            new DialogInterface.OnClickListener()
                                {

                                public void onClick(DialogInterface arg0,
                                        int arg1)
                                {
                                    bouncingBallView.resume();

                                }
                            })
                    .setNegativeButton("Exit",
                            new DialogInterface.OnClickListener() {

                                public void onClick(DialogInterface dialog,
                                        int which)
                                {
                                    BouncingBallActivity.this.finish();

                                }
                            });

            AlertDialog gameOverDialog = builder.create();
            return gameOverDialog;
        default:
            return null;
        }


    }


    class BouncingBallView extends SurfaceView implements Runnable
    {
        SurfaceHolder   surfaceViewHolder;
        Canvas          canvas;
        Context         context;
        Thread          drawingThread;

        boolean         drawingThreadIsRunning;
        boolean         isInitialised;

        Ball            ball;
        ArtificialIntelligence ai;

        BouncingBallView(Context context)
        {
            //
        }

        public void pause()
        {
            isInitialised = false;
            drawingThreadIsRunning = false;
            boolean joiningWasSuccessful = false;

            while(!joiningWasSuccessful)
            try {
                drawingThread.join();
                joiningWasSuccessful = true;
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

        public void resume()
        {
            isInitialised = false;
            drawingThread = new Thread(this);

            drawingThread.setName("Drawing Thread");
            drawingThreadIsRunning = true;
            drawingThread.start();

        }

        public void run()
        {
            while(drawingThreadIsRunning)
            {
                if(!surfaceViewHolder.getSurface().isValid())
                    continue;

                if(gameOver())
                    BouncingBallActivity.this.showDialog(DIALOG_GAMEOVER_ID);

                try{
                    canvas = surfaceViewHolder.lockCanvas();
                    if(!isInitialised)init(canvas);
                    update();
                    surfaceViewHolder.unlockCanvasAndPost(canvas);
                }catch(Exception e)
                {
                    Log.e(BouncingBallActivity.this.toString(),String.format("%s: Just as the emperor had foreseen!\n(This error is expected. Canvas destroyed while animations continue.)", e.toString()));
                }
            }
        }

        private void init(Canvas canvas)
        {
            ball = new Ball(canvas, Color.GREEN);
            ai   = new ArtificialIntelligence(canvas, (int) (ball.getX()+100),canvas.getWidth());

            isInitialised = true;
        }

    }
}

4 个答案:

答案 0 :(得分:2)

尝试这样......你不能从主线程以外的地方对ui进行任何更改..在 if(gameOver())

之后,在你的线程中输入这个部分
//if(gameOver())
 runOnUiThread(new Runnable() {
           @Override
           public void run() {

               BouncingBallActivity.this.showDialog(DIALOG_GAMEOVER_ID);
           }
       });

答案 1 :(得分:1)

您正在从worker(后台)线程调用Dialog。你需要从主线程调用它。尝试使用Activity.runOnUIThread()调用它并在其中创建一个处理程序,它将调用你的showDialog方法。

答案 2 :(得分:0)

我用[https://stackoverflow.com/a/16886486/3077964]来解决问题。

在runOnUiThread()中显示对话框后,您需要暂停BouncingBallView的线程。 那就是:

//if(gameOver()){       
BouncingBallActivity.this.runOnUiThread(new Runnable() {
 @Override
public void run() {    BouncingBallActivity.this.showDialog(DIALOG_GAMEOVER_ID);    }    });    pause();    }

答案 3 :(得分:0)

对我来说,我在surfaceView中使用了这个处理程序来创建dialogBox。

Handler someHandler = new Handler(){
//this method will handle the calls from other threads. 
public void handleMessage(Message msg) {

                 final Dialog dialog = new Dialog(Game.this);

                   dialog.setContentView(R.layout.question_dialog);
                   dialog.setTitle("GAME OVER");




                   Button restart=(Button)dialog.findViewById(R.id.btn Restart);

                   // Set On ClickListener
                   restart.setOnClickListener(new View.OnClickListener() {

                       public void onClick(View v) {


                               Toast.makeText(Game.this, "Restart Game", Toast.LENGTH_LONG).show();
                               dialog.dismiss();

                           }


                       }
                   });

                   dialog.show();

             }

所以,我在游戏线程中编写了looper.prepared()来调用这个Handler。如果播放器功率= 0,则会出现此对话框。

Looper.prepare();

 //create the message for the handler 
 Message status = someHandler.obtainMessage();
 Bundle data = new Bundle();
 String msgContent = null;
 data.putString("SOMETHING", msgContent);
 status.setData(data);
 someHandler.sendMessage(status);

 Looper.loop();

  }      
相关问题