好的,所以最初我认为问题在于每次按下停止然后启动时,都会创建一个新的runnable,因此我们将同时运行多个runnable,从而每次都更快更快地更新计时器。但它似乎不是问题:我通过添加布尔“运行”来更改代码,以便按下启动/停止只更改布尔变量。通过这种方式,我认为只有一个runnable正在运行。但是当我连续几次点击开始/停止时它仍然会变得更快。有人能告诉我问题在哪里吗?
package com.example.timernew;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
Handler h=new Handler();
TextView t;
Button start, stop,reset;
boolean running;
Runnable run=new Runnable() {
@Override public void run() { updateTime(); } };;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
t = (TextView) findViewById(R.id.TextArea);
start = (Button) findViewById(R.id.start_button);
stop=(Button) findViewById(R.id.stop_button);
running=false;
h.post(run);
start.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v){
if(running==false){
running=true;
}
}
});
stop.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v){
if(running==true){
running=false;
}
}
});
}
public void updateTime() {
if(running==true){
t.setText("" + (Integer.parseInt(t.getText().toString()) +1));
h.postDelayed(run, 1000);}
}
}
答案 0 :(得分:1)
我在开始按钮OnClickListenter中添加了对updateTime()的调用,并且在点击停止后计数继续没有问题。即使在等待10秒以上,再次点击开始只是从它停止的地方开始继续。
我确实注意到,如果我在击中停止后的1秒内开始,那么该值将连续快速增加两倍。这是因为点击开始调用updateTime()并且之前发布的runnable的延迟还没有完成,所以当它发生时,它也会增加时间。
更好的选择是使用AsyncTask:
package com.example.timernew;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
Handler h=new Handler();
TextView t;
Button start, stop,reset;
volatile boolean running;
UpdateTimeTask mUpdateTimeTask;
int counter = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
t = (TextView) findViewById(R.id.TextArea);
start = (Button) findViewById(R.id.start_button);
stop=(Button) findViewById(R.id.stop_button);
running=false;
start.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v){
if (null == mUpdateTimeTask) {
mUpdateTimeTask = new UpdateTimeTask();
mUpdateTimeTask.execute();
}
}
});
stop.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v){
if(null != mUpdateTimeTask) {
mUpdateTimeTask.cancel(true);
mUpdateTimeTask = null;
}
}
});
}
public class UpdateTimeTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
Log.e("timer app", "a problem occurred while sleeping or the task was cancelled", ie);
return null;
}
counter++;
publishProgress();
}
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
t.setText(String.valueOf(counter));
}
}
}
回答有关更改布尔值并调用updateTime()的问题:
在原始代码中,updateTime()仅在此行的onCreate()期间调用:
h.post(run);
由于您将布尔值设置为false,因此它不会执行任何操作并完成运行。
现在,假设你在start_button点击监听器中添加对updateTime()的调用,并快速连续点击start,stop,start all。这里发生了什么(假设每个发生的时间间隔为100毫秒):
0毫秒
click start将boolean设置为true,调用updateTime()
10ms的
调用updateTime(),boolean为true,因此它更改文本并发布runnable以便在1000ms内运行
100毫秒 click stop将布尔值设置为false
200毫秒 click start将boolean设置为true,调用updateTime()
210ms 调用updateTime(),boolean为true,因此它更改文本并发布runnable以便在1000ms内运行
1010ms 第一个发布的runnable运行,看到布尔值为true,更改文本并发布另一个runnable以便在1000ms内运行
1210ms 第二个发布的runnable运行,看到布尔值为true,更改文本,并发布另一个runnable
此时你的进入时间不到1.3秒,计数已经是3秒。现在,文本将从现在开始大约每n + .1和n + .2秒更改一次。