Search code examples
javaandroidandroid-studiotic-tac-toe

Sleep function not lagging in front of AI's turn


I need to add an artificial pause before my AI plays its turn on the tic tac toe board. However, when I try to use something like Thread.sleep, in the location where I have the comment, the entire onClick function lags. What I mean by lagging is that the ((Button) v).setText("0") does not set the button text to 0 for the amount of time I use the sleep function and the moment that the timer is up, everything happens immediately. It is like the lag happens in the beginning of the function rather than the middle where the comment is. Is there anyway to address this problem or explain why the sleep function isn't lagging where it is suppose to be?

public void onClick(View v) {

    if(!((Button) v).getText().toString().equals("")){
        return;
    }

    ((Button) v).setText("0");
    turn();

    // Need a pause before tictacAI does anything

    tictacAI("0", "X").setText("X");
    turn();
    if(won){
        resetBoard();
        won = false;
    }
}

Solution

  • When using Thread.sleep in onClick, you are actually blocking the entire UI Thread, This will prevent Android Framework redraw your view, so your change to View's property will not be displayed.

    In order to delay the execution, you should use View.postDelayed, which will post your action to a message queue and execute it later.

    public void onClick(View v) {
    
        if(!((Button) v).getText().toString().equals("")){
            return;
        }
    
        ((Button) v).setText("0");
        turn();
    
        // Need a pause before tictacAI does anything
        v.postDelayed(new Runnable() {
            @Override
            public void run() {
                tictacAI("0", "X").setText("X");
                turn();
                if(won){
                    resetBoard();
                    won = false;
                }
            }
        }, 1000L); //wait 1 second
    }
    

    If you are using Java 1.8, you can use lambda instead of anonymous class.

    Another note:
    this Runnable will not be garbage collected until executed, so a long interval may cause your entire view leaked, which is very bad. Consider using View.removeCallbacks when this callback is not needed anymore(like activity's onDestroy, for example)