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