【发布时间】:2017-02-14 11:21:00
【问题描述】:
我正在尝试使用随着时间推移不断更新的 EditText。这由一个线程处理,该线程调用一个方法来计算经过时间并将 EditText 文本设置为经过时间。线程每秒休眠一次。线程在用户按下“开始”时启动,并在用户按下“停止”时停止。当用户再次按下“开始”时,线程应该从 0 重新开始(因为开始时间已重置)。代码如下:
public class MainActivity extends AppCompatActivity {
public Date start;
public Date end;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startButton = (Button) findViewById(R.id.startButton);
Button endButton = (Button) findViewById(R.id.stopButton);
final EditText dateEditText = (EditText) findViewById(R.id.dateEditText) ;
final EditText hoursEditText = (EditText) findViewById(R.id.hoursEditText); //the one I want to update
final DateFormat df = new SimpleDateFormat("MM/dd/yy");
final Thread t = new Thread() {
@Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
@Override
public void run() {
setTimeElapsed(hoursEditText);
}
});
}
} catch (InterruptedException e) {
}
}
};
startButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
start = new Date();
dateEditText.setText(df.format(start));
hoursEditText.setText("");
t.start();
}
});
endButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
t.interrupt();
if (start == null) {
//write error message
}
else {
setTimeElapsed(hoursEditText);
start = null;
}
}
});
}
public void setTimeElapsed(EditText hoursEditText)
{
end = new Date();
long diff = end.getTime() - start.getTime();
String diffFormatted = String.format("%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(diff),
TimeUnit.MILLISECONDS.toMinutes(diff)
- TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(diff)),
TimeUnit.MILLISECONDS.toSeconds(diff)
- TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(diff)));
hoursEditText.setText(diffFormatted);
}
}
如您所见,问题是当我按“停止”然后再次按“开始”时,应用程序会抛出错误,因为线程已经在运行。如果我没有中断语句,则应用程序会崩溃,因为它认为start 为空。我只想在按下停止按钮时停止线程,并在按下开始时从 0 开始计数。
编辑:
我解决此问题的一种方法是创建一个新线程并在我的 startButton 侦听器中调用该方法
public void startThread(final EditText hoursEditText){
t = new Thread() {
@Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
@Override
public void run() {
setTimeElapsed(hoursEditText);
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
}
但这会在每次有人按下开始时创建一个新线程。这可不好。
【问题讨论】:
-
@jeremy 您可以为此使用带有计时器的 Handler。线程在这里是多余的。
-
但这会在每次有人按下开始时创建一个新线程。这不好。 - 为什么不呢?
-
测试这个的人可能会连续按下开始按钮 500 次。除非我错了,否则这将启动 500 个并发线程。
-
按Stop时为什么不终止线程?