Java 调用cancel()方法时,倒计时不会停止

Java 调用cancel()方法时,倒计时不会停止,java,android,Java,Android,我正在做一个简单的游戏,叫做“神奇的比赛”。 项目概述:有三种动物参加比赛的项目,包括猪、鸡和龟,让玩家猜测哪种动物将在比赛中获胜。 但是,我在CountDownTimer对象的cancel()方法中遇到了困难。我无法理解为什么cancel()方法不起作用(即使其中一个动物到达了目的地,但另外两个仍然运行到终点) 我程序的全部代码 package quynhanhhle.theamazingrace; import android.os.Bundle; import android.os.Co

我正在做一个简单的游戏,叫做“神奇的比赛”。 项目概述:有三种动物参加比赛的项目,包括猪、鸡和龟,让玩家猜测哪种动物将在比赛中获胜。 但是,我在CountDownTimer对象的cancel()方法中遇到了困难。我无法理解为什么cancel()方法不起作用(即使其中一个动物到达了目的地,但另外两个仍然运行到终点)

我程序的全部代码

package quynhanhhle.theamazingrace;

import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import java.util.Random;

public class MainActivity extends AppCompatActivity {
    TextView txtDiem;
    CheckBox chkGa, chkRua, chkLon;
    SeekBar skbGa, skbRua, skbLon;
    ImageButton btnBatDau;
    CountDownTimer countDownTimer;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        anhXa();

        xuLyCheckBox();

        chuongTrinhChinh();

        choiLai();
    }

    private void choiLai() {
        btnBatDau.setVisibility(View.VISIBLE);
        chkRua.setEnabled(true);
        chkLon.setEnabled(true);
        chkGa.setEnabled(true);
    }

    private void chuongTrinhChinh() {
        btnBatDau.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!(chkLon.isChecked() || chkGa.isChecked() || chkRua.isChecked())) {
                    Toast.makeText(MainActivity.this, "Đoán con vật chiến thắng", Toast.LENGTH_SHORT).show();
                } else {
                    btnBatDau.setVisibility(View.INVISIBLE);
                    chkGa.setEnabled(false);
                    chkLon.setEnabled(false);
                    chkRua.setEnabled(false);

                    countDownTimer = new CountDownTimer(10000, 300) {
                        @Override
                        public void onTick(long millisUntilFinished) {
                            Random rd = new Random();

                            if (skbGa.getProgress() >= skbGa.getMax()) {
                                this.cancel();
                                Toast.makeText(MainActivity.this, "Gà thắng", Toast.LENGTH_SHORT).show();
                            }
                            if (skbLon.getProgress() >= skbLon.getMax()) {
                                this.cancel();
                                Toast.makeText(MainActivity.this, "Lợn thắng", Toast.LENGTH_SHORT).show();
                            }
                            if (skbRua.getProgress() >= skbRua.getMax()) {
                                this.cancel();
                                Toast.makeText(MainActivity.this, "Rùa thắng", Toast.LENGTH_SHORT).show();
                            }

                            skbGa.setProgress(skbGa.getProgress() + (rd.nextInt(10) + 1));
                            skbLon.setProgress(skbLon.getProgress() + (rd.nextInt(10) + 1));
                            skbRua.setProgress(skbRua.getProgress() + (rd.nextInt(10) + 1));
                        }

                        @Override
                        public void onFinish() {

                        }
                    };

                    countDownTimer.start();
                }
            }
        });

    }

    private void xuLyCheckBox() {
        chkGa.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (chkGa.isChecked()){
                    chkLon.setChecked(false);
                    chkRua.setChecked(false);
                }
            }
        });

        chkLon.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (chkLon.isChecked()){
                    chkGa.setChecked(false);
                    chkRua.setChecked(false);
                }
            }
        });

        chkRua.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (chkRua.isChecked()){
                    chkGa.setChecked(false);
                    chkLon.setChecked(false);
                }
            }
        });
    }

    private void anhXa() {

        txtDiem = (TextView) findViewById(R.id.txtDiem);

        chkGa = (CheckBox) findViewById(R.id.chkGa);

        chkLon = (CheckBox) findViewById(R.id.chkLon);

        chkRua = (CheckBox) findViewById(R.id.chkRua);

        skbGa = (SeekBar) findViewById(R.id.skbGa);

        skbLon = (SeekBar) findViewById(R.id.skbLon);

        skbRua = (SeekBar) findViewById(R.id.skbRua);

        btnBatDau = (ImageButton) findViewById(R.id.btnBatDau);
    }
}

问题是每次单击btnBatDau时,您都在创建一个新的倒计时

我的建议是将倒计时初始化块放在活动的onCreate()中

调用
CountDownTimer#cancel()
(或者在您的示例中调用
this.cancel()
)没有问题。它会取消计时器,并且不会调用onTick()

看看这个例子。它正确地取消:

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

        timer = new CountDownTimer(10000, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                if(millisUntilFinished < 5000) {
                    this.cancel();
                }

                Log.d("Timer", millisUntilFinished + "");
            }

            @Override
            public void onFinish() {

            }
        };

        timer.start();
    }

您可以像这样实现自己的计时器

public class MainActivity extends AppCompatActivity {

    SeekBar seekBar1, seekBar2;
    Button start;

    Handler handler;
    Runnable timer;
    boolean running;

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

        seekBar1 = (SeekBar) findViewById(R.id.seek1);
        seekBar2 = (SeekBar) findViewById(R.id.seek2);
        start = (Button) findViewById(R.id.start_timer);

        start.setOnClickListener(startrListener);
    }

    private View.OnClickListener startListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            startTimer();
        }
    };

    private void startTimer() {
        handler = new Handler();
        timer = new Runnable() {
            @Override
            public void run() {
                if (!running) return;

                Random rd = new Random();

                if (seekBar1.getProgress() >= seekBar1.getMax())
                    stopTimer();
                if (seekBar2.getProgress() >= seekBar2.getMax())
                    stopTimer();

                seekBar1.setProgress(seekBar1.getProgress() + (rd.nextInt(10) + 1));
                seekBar2.setProgress(seekBar2.getProgress() + (rd.nextInt(10) + 1));

                handler.postDelayed(this, 300);
            }
        };
        handler.postDelayed(timer, 300);
        running = true;
    }

    private void stopTimer() {
        running = false;
        handler.removeCallbacks(timer);
    }

}

可能
btnBatDau.setOnClickListener
被多次激发?在创建前,请尝试检查是否未运行倒计时程序。您所说的“已触发”是什么意思?我试着阅读关于倒计时的android文档,它也有这个词,我不明白这个意思。我不是英语母语,但据我所知,
fired
是一种类似于
的东西,叫做
(在代码中)我明白了你的意思。你的代码似乎可以工作。您确定倒数计时器仍在运行吗?或者,
onTick
刚刚被再次调用?你的意思是我应该复制
countDownTimer=new countDownTimer。。。public void onFinish(){}
进入onCreate()?是的,您应该将其移动到onCreate。然后在你的按钮的onClickListener中,你可以启动你的计时器,如果你想的话。我试过了,但它仍然没有停止。我不理解“每次单击btnBatDau时创建一个新的倒计时器”的想法。你能帮我一下吗?我的意思是在游戏结束前不能多次点击btnBatDau,因为我已将其设置为不可见,因此它在游戏期间无法与玩家交互。你不需要多个倒计时实例。每次你按下按钮,你实际上是在创建一个It的实例,我仍然想从我的代码中知道这个问题。但是谢谢你,我会试试这个。
09-08 17:48:10.627 21140-21140/com.safaorhan.coundownsample D/Timer: 8954
09-08 17:48:11.629 21140-21140/com.safaorhan.coundownsample D/Timer: 7953
09-08 17:48:12.630 21140-21140/com.safaorhan.coundownsample D/Timer: 6952
09-08 17:48:13.631 21140-21140/com.safaorhan.coundownsample D/Timer: 5950
09-08 17:48:14.633 21140-21140/com.safaorhan.coundownsample D/Timer: 4949
public class MainActivity extends AppCompatActivity {

    SeekBar seekBar1, seekBar2;
    Button start;

    Handler handler;
    Runnable timer;
    boolean running;

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

        seekBar1 = (SeekBar) findViewById(R.id.seek1);
        seekBar2 = (SeekBar) findViewById(R.id.seek2);
        start = (Button) findViewById(R.id.start_timer);

        start.setOnClickListener(startrListener);
    }

    private View.OnClickListener startListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            startTimer();
        }
    };

    private void startTimer() {
        handler = new Handler();
        timer = new Runnable() {
            @Override
            public void run() {
                if (!running) return;

                Random rd = new Random();

                if (seekBar1.getProgress() >= seekBar1.getMax())
                    stopTimer();
                if (seekBar2.getProgress() >= seekBar2.getMax())
                    stopTimer();

                seekBar1.setProgress(seekBar1.getProgress() + (rd.nextInt(10) + 1));
                seekBar2.setProgress(seekBar2.getProgress() + (rd.nextInt(10) + 1));

                handler.postDelayed(this, 300);
            }
        };
        handler.postDelayed(timer, 300);
        running = true;
    }

    private void stopTimer() {
        running = false;
        handler.removeCallbacks(timer);
    }

}