1

我已经尝试了一些方法来做到这一点并且没有secced。我有启动 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. 实例化多个 WorkerThread 并获取对其 Handler 对象的引用。

  5. 在每一帧中,使用 postRunnable() 方法将定义您希望线程执行的逻辑的 Runnable() 传递给 Handler。
  6. 使用 ConditionVariable 对象确保在 WorkerThread 仍在执行时不调用 postRunnable() 方法。

    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 的变量。享受自动启动和停止!

将此方法应用于您不想逐帧同步的三个不同线程可能会出现问题。让我知道事情的后续。

于 2013-08-28T20:53:00.030 回答