web-dev-qa-db-fra.com

comment utiliser postDelayed () correctement dans Android studio?

J'ai un countDownTimer et si l'utilisateur ne frappe pas le bouton de jeu dans les 12 secondes, je veux que la méthode gameOver s'appelle. Le problème est que la fonction de jeu soit appelée instantanément lorsque countDownTimer est à 12 ou que la minuterie continue à décompter. Donc, j'essaie d'utiliser la méthode postDelayed () pour donner à l'utilisateur une seconde complète d'appuyer sur le bouton et laisser le décompte countDownTimer se poursuivre, mais comme mon code est en ce moment, le jeu s'arrête à 12 malgré tout.

import Android.app.Activity;
import Android.os.CountDownTimer;
import Android.os.Handler;
import Android.support.v7.app.AppCompatActivity;
import Android.os.Bundle;
import Android.view.View;
import Android.widget.Button;
import Android.widget.TextView;
import Android.widget.Toast;



public class GameScreen extends Activity {

    private TextView time;
    private Button start;
    private Button cancel;
    private Button gameButton;
    private CountDownTimer countDownTimer;
    public static int count = 0;
    public static int countFail = 0;

    final Handler handler = new Handler();
    final Runnable r = new Runnable() {
        public void run() {
            handler.postDelayed(this, 1000);
            gameOver();
        }
    };


    private View.OnClickListener btnClickListener = new View.OnClickListener(){

        @Override
        public void onClick(View v) {

            switch(v.getId()){
                case R.id.start_ID :
                    start();
                    break;
                case R.id.cancel :
                    cancel();
                    break;
                case R.id.gameButton_ID :
                    gameButton();
                    break;
            }

        }


    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_game_screen);


        start = (Button) findViewById(R.id.start_ID);
        start.setOnClickListener(btnClickListener);
        cancel = (Button) findViewById(R.id.cancel);
        cancel.setOnClickListener(btnClickListener);
        time = (TextView) findViewById(R.id.time);
        gameButton = (Button) findViewById(R.id.gameButton_ID);
        gameButton.setOnClickListener(btnClickListener);


    }

    public void start(){

        time.setText("16");
        //This doesn't work and makes app crash when you hit start button

        countDownTimer = new CountDownTimer(16 * 1000, 1000) {
            @Override
            public void onTick(long millsUntilFinished){
                time.setText("" + millsUntilFinished / 1000);

                //turns textview string to int
                int foo = Integer.parseInt(time.getText().toString());

                if(time.getText().equals("12")){

                    r.run();

                }

            }

            public void onFinish() {
                time.setText("Done !");
            }
        };
        countDownTimer.start();
    }

    private void cancel(){
        if(countDownTimer != null){
            countDownTimer.cancel();
            countDownTimer = null;
        }
    }

    private void gameOver(){
        Toast.makeText(getApplicationContext(), "You scored " + count, Toast.LENGTH_SHORT).show();
        count = 0;
        countFail = 0;
        cancel();
    }

    private void gameButton(){

        int foo = Integer.parseInt(time.getText().toString());

        if(foo  % 2 == 0 ) {
            Toast.makeText(getApplicationContext(), "PASS", Toast.LENGTH_SHORT).show();
            handler.removeCallbacks(r);
            ++count;
        }

        else{
            gameOver();
        }
    }

}
22
Ryder Thacker

Vous utilisez presque postDelayed(Runnable, long) correctement, mais pas tout à fait. Jetons un coup d'oeil à votre Runnable.

final Runnable r = new Runnable() {
    public void run() {
        handler.postDelayed(this, 1000);
        gameOver();
    }
};

Lorsque nous appelons r.run();, la première chose à faire est de dire à votre handler de lancer le même Runnable après 1000 millisecondes, puis d'appeler gameOver(). En réalité, votre méthode gameOver() sera appelée deux fois: une fois tout de suite, et une seconde fois, une fois que le gestionnaire aura terminé, il attendra 1000 millisecondes.

Au lieu de cela, vous devriez changer votre Runnable en ceci:

final Runnable r = new Runnable() {
    public void run() {
        gameOver();
    }
};

Et appelez ça comme ça:

handler.postDelayed(r, 1000);

J'espère que cela t'aides.

52
DanielLaneDC

Vous trouverez ci-dessous le code que j’utilise, qui fonctionne de la même manière que la réponse acceptée, mais est assez simple à écrire et à comprendre.

final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    //Write whatever to want to do after delay specified (1 sec)
                    Log.d("Handler", "Running Handler");
                }
            }, 1000);