androidmultithreadingsynchronoushandlers

Android handler running asynchronously


I have a function, gamePlay(), which looks like this:

 public void gamePlay()
{
    for (int i = 0; i < 4; i++)
    {
        currentRound = i;
        if (i == 0)
        {
            simulateTurns();
        }
        if(i == 1)
        {
            simulateTurns();
        }
        if (i > 1)
        {
           simulateTurns();
        }
    }
}

simulateTurns() uses a Handler instantiated with the Looper.getMainLooper() parameter as follows before gamePlay() is ever called:

thread = new Handler(Looper.getMainLooper());

simulateTurns():

public void simulateTurns()
{
    currentPlayer = players[playerIndex % numPlayers];

    if(currentPlayer.getPlayerID() == USER_ID) //user
    {
        if(!currentPlayer.hasFolded())
            showUserOptions(currentRound);
        else
        {
            playerIndex++;
            simulateTurns();
        }
    }
    else
    {
        hideUserOptions(0);

        // Give players the option to raise, call, fold, checking (dumb for now, needs AI and user input)
        // currentPlayer.getPlayerID() gets the current ID of the player
        int randAction = (int) (Math.random() * 4);
        String action = "";


        //DEBUG Simulate game
        Log.w("--------DEBUG--------", "Round: " + currentRound + " Bot: " + currentPlayer.getPlayerID() + " action: " + action + " pot: " + pot);

        thread.postDelayed(new Runnable(){
            public void run()
            {
                if(!betsEqual())
                    simulateTurns();
            }}, 5000);
    }
}

When debugging the log, all rounds seem to start in parallel and then a few turns of round 3 are logged.

How can I get the for loop to run in sync with simulateGame() so that the rounds run in order?

Note: I also call simulateTurns() on a few onClickListeners.


Solution

  • Your code seems confusing. If you are trying to simulate a turn in order, you should not use asynchrone functions, because it's intended to be asynchrone, and you are not seeking for that behavior.

    Assuming you're trying to do asynchrone things because you're waiting for things to happen (or because you don't want to block UI thread), you will have to do some changes before doing everything.

    You are using a global variable for round count. This mean your loop is executing really fast launching everything then the asynchrones call are executed, therefore, the variable is max (3) for all call.

    You should have a function called "StartNextRound()" wich is called at the end of your "simulateTurn()". This function should check whereas it is needed to start a new round (i<4) then call a new instance of your simulateTurn().

    Let's sum this up: don't launch the asynchrone task before it is needed. Use a function to launch a new round, and call that function at end of previous round.

    That's the easiest way to deal with asynchrone. Other options are more complicated (and probably not memory efficient) and involve handlers between the threads in order to be able to launch all tasks at once and make them sleep until the correct round is started. That's a very hard work to keep something that is not really correct (and seems to be there "for test" purposes).