как правильно использовать postDelayed() в андроид-студии?
У меня есть countDownTimer, и если пользователь не нажимает кнопку gameButton в течение 12 секунд, я хочу вызвать метод gameOver. проблема Я либо получаю игровую функцию, вызываемую немедленно, когда countDownTimer равен 12, или таймер просто продолжает обратный отсчет. Поэтому я пытаюсь использовать метод postDelayed(), чтобы дать пользователю целую секунду, чтобы нажать кнопку и позволить countDownTimer продолжить, но, поскольку мой код установлен прямо сейчас, игра останавливается на 12 независимо от этого.
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();
}
}
}
Ответы
Ответ 1
Вы почти используете postDelayed(Runnable, long)
правильно, но просто не совсем. Позвольте взглянуть на ваш Runnable.
final Runnable r = new Runnable() {
public void run() {
handler.postDelayed(this, 1000);
gameOver();
}
};
Когда мы вызываем r.run();
первое, что он собирается сделать, это сказать, что ваш handler
запускает тот же Runnable после 1000 миллисекунд, а затем вызывает gameOver()
. На самом деле это приведет к тому, что ваш gameOver()
дважды: один раз сразу, а второй раз, когда обработчик выполняется в ожидании 1000 миллисекунд.
Вместо этого вы должны изменить свой Runnable на это:
final Runnable r = new Runnable() {
public void run() {
gameOver();
}
};
И назовите это так:
handler.postDelayed(r, 1000);
Надеюсь это поможет.
Ответ 2
Ниже приведен код, который я использую, который работает так же, как принятый ответ, но довольно прост для написания и понимания.
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);