如何在 Android Studio 中正确使用 postDelayed()?
How to use postDelayed() correctly in Android Studio?
我有一个 countDownTimer,如果用户在 12 秒内没有点击 gameButton,我希望调用 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();
}
}
}
您几乎可以正确使用 postDelayed(Runnable, long)
,但不完全正确。让我们看看你的Runnable。
final Runnable r = new Runnable() {
public void run() {
handler.postDelayed(this, 1000);
gameOver();
}
};
当我们调用 r.run();
时,它要做的第一件事是在 1000 毫秒后将 handler
告诉 运行 完全相同的 Runnable,然后调用 gameOver()
.这实际上会导致您的 gameOver()
方法被调用两次:一次是立即调用,第二次是在处理程序完成后等待 1000 毫秒。
相反,您应该将 Runnable 更改为:
final Runnable r = new Runnable() {
public void run() {
gameOver();
}
};
并这样称呼它:
handler.postDelayed(r, 1000);
希望对您有所帮助。
下面是我使用的代码,它的工作原理与公认的答案相同,但编写和理解起来非常简单。
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()
不推荐使用无参数的 Handler 构造函数,不使用 lambda 也会使代码看起来笨拙,话虽这么说,但它看起来更现代:
final Runnable _r_ = new Runnable(){...};
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(() -> _r_.run(), 666);
您也可以更新它以使用方法参考
handler.postDelayed(_r_::run(), 666);
或者更简单,只需要一个限定符
handler.postDelayed(_r_, 666);
看到这个例子,应该就这么简单了:
Handler().postDelayed({
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
}, 4000) // delaying for 4 seconds...
我有一个 countDownTimer,如果用户在 12 秒内没有点击 gameButton,我希望调用 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();
}
}
}
您几乎可以正确使用 postDelayed(Runnable, long)
,但不完全正确。让我们看看你的Runnable。
final Runnable r = new Runnable() {
public void run() {
handler.postDelayed(this, 1000);
gameOver();
}
};
当我们调用 r.run();
时,它要做的第一件事是在 1000 毫秒后将 handler
告诉 运行 完全相同的 Runnable,然后调用 gameOver()
.这实际上会导致您的 gameOver()
方法被调用两次:一次是立即调用,第二次是在处理程序完成后等待 1000 毫秒。
相反,您应该将 Runnable 更改为:
final Runnable r = new Runnable() {
public void run() {
gameOver();
}
};
并这样称呼它:
handler.postDelayed(r, 1000);
希望对您有所帮助。
下面是我使用的代码,它的工作原理与公认的答案相同,但编写和理解起来非常简单。
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()
不推荐使用无参数的 Handler 构造函数,不使用 lambda 也会使代码看起来笨拙,话虽这么说,但它看起来更现代:
final Runnable _r_ = new Runnable(){...};
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(() -> _r_.run(), 666);
您也可以更新它以使用方法参考
handler.postDelayed(_r_::run(), 666);
或者更简单,只需要一个限定符
handler.postDelayed(_r_, 666);
看到这个例子,应该就这么简单了:
Handler().postDelayed({
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
}, 4000) // delaying for 4 seconds...