添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I have a countDownTimer and if the user does not hit the gameButton within the 12th second I want the gameOver method called.

The problem is that either the game function instantly gets called when the countDownTimer is 12 or the timer just keeps counting down.

So I am trying to use the postDelayed() method to give the user a full second to hit the button and let the countDownTimer continue, but as my code is right now the game stops on 12 regardless.

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();

You're almost using postDelayed(Runnable, long) correctly, but just not quite. Let's take a look at your Runnable.

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

When we call r.run(); the first thing it's going to do is tell your handler to run the very same Runnable after 1000 milliseconds, and then to call gameOver(). What this will actually result in is your gameOver() method being called twice: once right away, and a second time once the Handler is done waiting 1000 milliseconds.

Instead, you should change your Runnable to this:

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

And call it like this:

handler.postDelayed(r, 1000);
                @DanielLaneDC  said that "handler to run the very same Runnable after 1000 milliseconds" ,but the Runnable also includes the gameover() method that should be executed each time whenever the run method executes.
– Shivanshu
                Apr 6, 2019 at 13:58
                Isn't the gameOver() called infinitely every second, rather than being called twice? It looks like infinite recursion.
– starriet
                Jan 3, 2021 at 3:37

Below is the code that I use which works same as the accepted answer but is quite simple to write and understand.

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);
Thread(Runnable {
    // background work here ... 
    Handler(Looper.getMainLooper()).postDelayed(Runnable {
        // Update UI here ...
    }, 10000) // It will wait 10 sec before updating UI
}).start()

Using a parameterless Handler constructor is deprecated, and not using lambdas also make the code look clunky, so with that being said, here's how it looks a more modern use:

final Runnable _r_ = new Runnable(){...};
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(() -> _r_.run(), 666);

You might also update it to use method reference

handler.postDelayed(_r_::run(), 666);

Or more simple with just a qualifier

handler.postDelayed(_r_, 666);

Saw this example, should be as easy as that :

Handler().postDelayed({
    val intent = Intent(this, MainActivity::class.java)
    startActivity(intent)
    finish()
}, 4000) // delaying for 4 seconds...
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.

InputMethodManager.showInputMethodPicker not showing when custom keyboard in my app is not currently selected See more linked questions