1

私はそれを行うためにいくつかの方法を試しましたが、分離しませんでした。3 つのスレッドを開始する MainActivity があります。ユーザーが「戻る」ボタンを押したとき、または何らかの理由でアプリが停止したとき(電話など)にスレッドを停止したい。アクティビティが再び表示された後 (ユーザーがアプリに戻ったとき)、スレッドは停止した場所から続行されます。MainActivity で定義されたすべてのスレッドが開始されます。ありがとう!

public class MainActivity extends Activity
{

    //threads
    private PingPongGame gameThread;
    private PaddleMover paddleMoverThread;
    private PresentThread giftThread;


    public GameSounds gameSounds;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);


        gameLevel = new GameLevel0(screenWidth , screenHeight, this.giftArr);

        gameLevelView = new GameLevelView(this,gameLevel);

        // Creating the game view
        this.gameView = new PingPongView(this);


        // Setting the gameView as the main view for the PingPong activity.
        setContentView(gameView);


if(gameThread == null){
        //create the main thread
        gameThread = new PingPongGame( gamePaddle, gameView, gameLevel , message , ballArr , gameSounds);

        //create the thread responsible for moving the paddle
        paddleMoverThread = new PaddleMover(gamePaddle, gameView);

        //create the thread responsible for present
        giftThread = new  PresentThread(gamePaddle , gameView , gameLevel, message ,  giftArr , ballArr,gameSounds );

        gameThread.start();
        paddleMoverThread.start();
        giftThread.start();

}
    }

    //This method is automatically called when the user touches the screen
    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        float destination;
    //  Toast.makeText(this, "try!", Toast.LENGTH_SHORT).show();
        //get the x coordinate of users' press
        destination = event.getX();

        //notify the paddle mover thread regarding the new destination
        gamePaddle.setPaddleDestination(destination);

        return true;
    }
}

私のスレッドの例:

public class PaddleMover extends Thread
{
    private Tray gamePaddle; //holds a reference to the paddle
    private PingPongView gameView; //holds a reference to the main view

    //for stop
    private Object mPauseLock;
    private boolean mPaused;


    //initialize class variables
    public PaddleMover(Tray thePaddle, PingPongView mainView)
    {
        gamePaddle = thePaddle;
        gameView = mainView;

        //for stop and resume threads
        mPauseLock = new Object();
        mPaused = false;
    }

    //main method of the current thread
    @Override
    public void run()
    {
        //infinitely loop, and move the paddle if necessary
        while ((Const.isLose == false) && (Const.isCompleteThisLevel==false) && (Const.isDestroy == false))
        {
            //check whether the paddle should be moved
            if (gamePaddle.getMiddle() != gamePaddle.getPaddleDestination())
            {
                //move the paddle
                gamePaddle.move();

                //send a request to refresh the display
                gameView.postInvalidate();
            }
            try
            {
                PaddleMover.sleep(3);
            }
            catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            //for stop and resume
            synchronized (mPauseLock) {
                while (mPaused) {
                    try {
                        mPauseLock.wait();
                    } catch (InterruptedException e) {
                    }
                }
            }

        }
    }
    /**
     * Call this on pause.
     */
    public void onPause() {
        synchronized (mPauseLock) {
            mPaused = true;
        }
    }

    /**
     * Call this on resume.
     */
    public void onResume() {
        synchronized (mPauseLock) {
            mPaused = false;
            mPauseLock.notifyAll();
        }
    }
}
4

1 に答える 1

0

Runnable オブジェクトを使用すると、スレッドをより適切に制御できます。run() メソッド内でループを使用してロジックを定義する代わりに、次のようにします。

  1. Runnable オブジェクト内の各スレッドのフレーム単位のロジックを定義します。run() メソッドをオーバーライドします。Runnable 内で while ループを使用しないでください。

  2. ゲームが一時停止されているかどうかを追跡する変数を作成します。この変数を使用して、メイン スレッド内に単一の while() ループを作成します。

  3. Thread クラスを定義し、その Handler を取得します。これは次のように行うことができます。

    class WorkerThread extends Thread
    {
        private volatile Handler mHandler;
        //volatile so you can try to acquire it until it is instantiated
    
        @Override
        public void run()
        {
            //This is pretty much boilerplate for worker thread implementations
            Looper.prepare();
            //Handlers must be instantiated by their respective threads
            mHandler = new Handler();
            Looper.loop();
        }
    
        @Override
        public Handler getHandler()
        {
            return mHandler;
        }
    }
    
  4. 複数の WorkerThreads をインスタンス化し、それらの Handler オブジェクトへの参照を取得します。

  5. 各フレームで、スレッドが実行するロジックを定義する Runnable() を postRunnable() メソッドを使用してハンドラに渡します。
  6. WorkerThread の実行中に postRunnable() メソッドを呼び出さないように、ConditionVariable オブジェクトを使用します。

    Runnable thread1runnable = new Runnable()
    {
         @Override
         public void run()
         {
             //Do your logic here
             ...
             thread1finished.open();    //This lets the block() function return
         }
     }
    
    ConditionVariable thread1finished = new ConditionVariable();
    
    thread1finished.open(); //Make sure the loop doesn't block the first time through
    
    Thread thread1 = new WorkerThread();
    //Start the thread to acquire the handler and prepare it for looping
    thread1.start();
    //Call stop() when shutting down your game, not pausing
    
    Handler thread1handler;
    while (thread1handler != null)
         thread1handler = thread1.getHandler();
    //A crude way of making sure you acquire the instantiated handler, you can top this
    
    while (gameRunning)
    {
        if (!isPaused)    //Stops work when your isPaused variable is set
        {
             thread1finished.block();    //Wait for the last runnable to finish
             //Lock the ConditionVariable so the loop will block
             thread1finished.close();
             //Signal the worker thread to start crunching
             thread1handler.postRunnable(thread1runnable);
        }
    }
    
  7. onPause() オーバーライドで、while() ループが Runnable オブジェクトを WorkerThreads に送信するのを停止する変数を設定します。自動発停を楽しもう!

フレームごとに同期させたくない 3 つの異なるスレッドにこのメソッドを適用すると、問題が発生する可能性があります。それがどうなるか教えてください。

于 2013-08-28T20:53:00.030 に答える