我的主要目的是:每10分钟,该应用程序同步服务器上的时间。然后,时钟将从服务器的时间开始,而倒计时时钟将显示剩余的时间,直到下一次同步。
我的代码如下。似乎线程每10分钟重新创建一次,因此时钟显示错误。但是,我不知道如何解决它。请帮我。谢谢!
public class MainActivity extends Activity {
private AnalogClockView analogClockView;
private FrameLayout analogLayout;
private long now;
private ClockAsyncTask mClockAsyncTask;
private CountDownTimer mCountDownTimer = new CountDownTimer(10*60*1000, 1000) {
@Override
public void onFinish() {
mClockAsyncTask = (ClockAsyncTask) new ClockAsyncTask();
mClockAsyncTask.execute();
}
@Override
public void onTick(long millisUntilFinished) {
// TODO Auto-generated method stub
analogClockView.updateTime();
analogClockView.postInvalidate();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
analogLayout = (FrameLayout) findViewById(R.id.analogLayout);
mCountDownTimer.start();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class ClockAsyncTask extends AsyncTask<Object, Object, Object> {
@Override
protected Object doInBackground(Object... arg0) {
getNTPTime();
return null;
}
@Override
protected void onPostExecute(Object result) {
analogClockView = new AnalogClockView(MainActivity.this, now, analogLayout.getWidth()/2, analogLayout.getHeight()/2);
analogLayout.removeAllViews();
analogLayout.addView(analogClockView);
}
}
public void getNTPTime(){
SntpClient client = new SntpClient();
if (client.requestTime("0.ubuntu.pool.ntp.org", 1000)) {
now = client.getNtpTime() + SystemClock.elapsedRealtime()
- client.getNtpTimeReference();
Calendar current = Calendar.getInstance();
current.setTimeInMillis(now);
}
}
}
答案 0 :(得分:1)
问题是代码将相同的 Runnable用于线程返回到postDelayed而没有结束。线程仅运行一段非常短暂的时间,但代码会不断发布消息(并且每条消息都会发布另一条消息(并且每条消息都会发布...)。
然后,一个解决方案是使用变量来决定何时不发布另一个事件。
// Not really a "Thread"
public class CountdownRunner implements Runnable {
public void run() {
if (countdownRunning) {
MainActivity.this.updateHandler.sendEmptyMessage(0);
// STOP calling when then the countdown is over
// The fundamental problem is this series of delayed postbacks
// is never sopped in the original code.
updateHandler.postDelayed(this, 1000);
}
}
public void cancel() {
// ..
}
}
此外, ditch 创建新线程,因为显式线程在这里没有用处:提供的Runnable的run方法只在线程上调用一次,然后线程死亡。 (后续调用run方法在UI线程上以响应postDelayed回调。)
private CountdownRunner countdown;
protected void onPostExecute(Object result) {
// Start the countdown with the time from the server,
// cancelling the previous countdown as required.
if (countdown != null) {
countdown.cancel();
}
// No "new Thread"! this is running on the UI thread and all
// subsequent executions of run for this instance will also be
// on the UI thread in the postDelayed postback.
countdown = new CountdownRunner();
countdown.run();
}
虽然上面的解释了问题,但我建议只使用CountDownTimer,因为它很好地封装了逻辑:
[CountDownTimer计划]倒计时,直到将来的某个时间,并在整个过程中定期发出通知。
然后流程就像这样:
创建一个CountDownTimer并使用每个onTick
剩余的时间更新UI。当倒计时结束并且onFinish
事件触发时,创建一个新的AsyncTask。
让AsyncTask(即ClockAsyncTask)下载doInBackground
方法中的时间。在onPostExecute
方法中,创建一个新的CountDownTimer。
无限期重复此循环;确保根据需要取消任何CountDownTimers。