即使 CountDownTimer 过期,处理程序仍然是 运行
Handler is still running even though the CountDownTimer expires
我创建了一个处理程序来显示不同的骰子图像,而我的可运行对象是 运行。
通常,当我按下 "Roll" 按钮时,我的计时器从 3 开始倒计时,应用程序显示骰子的值。但有时,即使计时器到期,图像仍会继续变化。
我认为我的可运行程序仍在后台 运行。那么,Hhw 我可以在计时器到期时完全停止我的处理程序吗?
package com.basarballioz.dicerollerdroid;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Random;
public class OneDiceActivity extends AppCompatActivity {
TextView diceStatus;
Handler handler;
Runnable runnable;
ImageView diceView;
Button rollButton;
CountDownTimer rollTimer = null;
int diceNumber;
TextView diceResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.one_dice_activity);
//MAKE APPLICATION FULLSCREEN
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
diceStatus = findViewById(R.id.diceStatus);
rollButton = findViewById(R.id.rollButton);
diceView = findViewById(R.id.diceView);
diceResult = findViewById(R.id.diceResult);
diceStatus.setText("Press Roll!");
//Enable this ONLY IF you want to use OnClickListener method instead of onclick button
/*diceView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//rollDice();
}
});*/
}
public void rollDice(View view) {
diceStatus.setText("Rolling...");
rollTimer = new CountDownTimer(3000, 1000) {
@Override
public void onTick(final long millisUntilFinished) {
rollButton.setEnabled(false);
handler = new Handler();
runnable = new Runnable() {
@Override
public void run() {
Random ranNumber = new Random();
diceNumber = ranNumber.nextInt(6) + 1;
switch (diceNumber) {
case 1:
diceView.setImageResource(R.drawable.dice1);
diceResult.setText("1");
break;
case 2:
diceView.setImageResource(R.drawable.dice2);
diceResult.setText("2");
break;
case 3:
diceView.setImageResource(R.drawable.dice3);
diceResult.setText("3");
break;
case 4:
diceView.setImageResource(R.drawable.dice4);
diceResult.setText("4");
break;
case 5:
diceView.setImageResource(R.drawable.dice5);
diceResult.setText("5");
break;
case 6:
diceView.setImageResource(R.drawable.dice6);
diceResult.setText("6");
break;
default:
break;
}
handler.postDelayed(runnable, 100);
}
};
handler.post(runnable);
}
@Override
public void onFinish() {
rollButton.setEnabled(true);
showDiceNumber();
handler.removeCallbacks(runnable);
}
}.start();
}
public void showDiceNumber() {
diceStatus.setText("Your dice is: ");
}
@Override
public void onBackPressed() {
finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
应用程序的 GitHub link:https://github.com/basarballioz/Dice-Rollerdroid
这一行
new CountDownTimer(3000, 1000)
创建一个倒数计时器,在 1 秒后、2 秒后以及可能在 3 秒后调用 onTick
(不相关但值得验证)。
在 onTick
的每次调用(2 或 3 次调用)中,您创建一个新的处理程序并分配给它:
handler = new Handler();
和post
它。每次每个处理程序完成时(现在是 2 或 3 个处理程序),它们会在 100 毫秒后重新安排:
handler.postDelayed(runnable, 100);
注意 运行nable 实例也被重新创建,这不是必需的。
当 onFinish
被调用时(在 2 或 3 个滴答声之后)- 有 2 或 3 个处理程序 运行每 100 毫秒重复一次。
只有最后一个处理程序或(第 2 个或第 3 个)被 onFinish
取消,最初的 1 或 2 个处理程序继续 运行。
图片...
您绝对不需要超过 1 个处理程序和 运行nable 实例 - 事实上,您根本不需要处理程序,因为 CountDownTimer
基本上已经这样做了。您是使用 CountDownTimer
还是仅使用带计数器的普通 Handler
由您决定。
如果希望在 1 秒延迟后每 100 毫秒改变一次骰子面(显示的值)持续 3 秒,然后将 onTick
更改为仅启动处理程序一次(或完全消除处理程序 - 请参阅建议的代码)。 (请注意,当前实施在 初始 1 秒后开始更改骰子 。)
(可能需要在 post 中说明您 真正 想要发生的事情。)
引用的库未正确实现。
我建议采用一种更简单的方法来消除 CountDownTimer 代码的冗余:
public void rollDice(View view) {
diceStatus.setText("Rolling...");
// Note the random is only created once.
final Random ranNumber = new Random();
rollButton.setEnabled(false);
// updates every 100 millis after an initial 100milli delay.
rollTimer = new CountDownTimer(3000, 100) {
@Override
public void onTick(final long millisUntilFinished) {
diceNumber = ranNumber.nextInt(6) + 1;
// use same switch statement as original post - sets the dice face.
}
@Override
public void onFinish() {
rollButton.setEnabled(true);
showDiceNumber();
}
}.start();
}
如果你真的需要在滚动之前有 1 秒的初始延迟,那么不要立即 start()
而是添加类似的内容:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
rollTimer.start();
}
}, 1000);
我创建了一个处理程序来显示不同的骰子图像,而我的可运行对象是 运行。 通常,当我按下 "Roll" 按钮时,我的计时器从 3 开始倒计时,应用程序显示骰子的值。但有时,即使计时器到期,图像仍会继续变化。
我认为我的可运行程序仍在后台 运行。那么,Hhw 我可以在计时器到期时完全停止我的处理程序吗?
package com.basarballioz.dicerollerdroid;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Random;
public class OneDiceActivity extends AppCompatActivity {
TextView diceStatus;
Handler handler;
Runnable runnable;
ImageView diceView;
Button rollButton;
CountDownTimer rollTimer = null;
int diceNumber;
TextView diceResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.one_dice_activity);
//MAKE APPLICATION FULLSCREEN
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
diceStatus = findViewById(R.id.diceStatus);
rollButton = findViewById(R.id.rollButton);
diceView = findViewById(R.id.diceView);
diceResult = findViewById(R.id.diceResult);
diceStatus.setText("Press Roll!");
//Enable this ONLY IF you want to use OnClickListener method instead of onclick button
/*diceView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//rollDice();
}
});*/
}
public void rollDice(View view) {
diceStatus.setText("Rolling...");
rollTimer = new CountDownTimer(3000, 1000) {
@Override
public void onTick(final long millisUntilFinished) {
rollButton.setEnabled(false);
handler = new Handler();
runnable = new Runnable() {
@Override
public void run() {
Random ranNumber = new Random();
diceNumber = ranNumber.nextInt(6) + 1;
switch (diceNumber) {
case 1:
diceView.setImageResource(R.drawable.dice1);
diceResult.setText("1");
break;
case 2:
diceView.setImageResource(R.drawable.dice2);
diceResult.setText("2");
break;
case 3:
diceView.setImageResource(R.drawable.dice3);
diceResult.setText("3");
break;
case 4:
diceView.setImageResource(R.drawable.dice4);
diceResult.setText("4");
break;
case 5:
diceView.setImageResource(R.drawable.dice5);
diceResult.setText("5");
break;
case 6:
diceView.setImageResource(R.drawable.dice6);
diceResult.setText("6");
break;
default:
break;
}
handler.postDelayed(runnable, 100);
}
};
handler.post(runnable);
}
@Override
public void onFinish() {
rollButton.setEnabled(true);
showDiceNumber();
handler.removeCallbacks(runnable);
}
}.start();
}
public void showDiceNumber() {
diceStatus.setText("Your dice is: ");
}
@Override
public void onBackPressed() {
finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
应用程序的 GitHub link:https://github.com/basarballioz/Dice-Rollerdroid
这一行
new CountDownTimer(3000, 1000)
创建一个倒数计时器,在 1 秒后、2 秒后以及可能在 3 秒后调用 onTick
(不相关但值得验证)。
在 onTick
的每次调用(2 或 3 次调用)中,您创建一个新的处理程序并分配给它:
handler = new Handler();
和post
它。每次每个处理程序完成时(现在是 2 或 3 个处理程序),它们会在 100 毫秒后重新安排:
handler.postDelayed(runnable, 100);
注意 运行nable 实例也被重新创建,这不是必需的。
当 onFinish
被调用时(在 2 或 3 个滴答声之后)- 有 2 或 3 个处理程序 运行每 100 毫秒重复一次。
只有最后一个处理程序或(第 2 个或第 3 个)被 onFinish
取消,最初的 1 或 2 个处理程序继续 运行。
图片...
您绝对不需要超过 1 个处理程序和 运行nable 实例 - 事实上,您根本不需要处理程序,因为 CountDownTimer
基本上已经这样做了。您是使用 CountDownTimer
还是仅使用带计数器的普通 Handler
由您决定。
如果希望在 1 秒延迟后每 100 毫秒改变一次骰子面(显示的值)持续 3 秒,然后将 onTick
更改为仅启动处理程序一次(或完全消除处理程序 - 请参阅建议的代码)。 (请注意,当前实施在 初始 1 秒后开始更改骰子 。)
(可能需要在 post 中说明您 真正 想要发生的事情。)
引用的库未正确实现。
我建议采用一种更简单的方法来消除 CountDownTimer 代码的冗余:
public void rollDice(View view) {
diceStatus.setText("Rolling...");
// Note the random is only created once.
final Random ranNumber = new Random();
rollButton.setEnabled(false);
// updates every 100 millis after an initial 100milli delay.
rollTimer = new CountDownTimer(3000, 100) {
@Override
public void onTick(final long millisUntilFinished) {
diceNumber = ranNumber.nextInt(6) + 1;
// use same switch statement as original post - sets the dice face.
}
@Override
public void onFinish() {
rollButton.setEnabled(true);
showDiceNumber();
}
}.start();
}
如果你真的需要在滚动之前有 1 秒的初始延迟,那么不要立即 start()
而是添加类似的内容:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
rollTimer.start();
}
}, 1000);