首先要给计时器定义三个状态:准备,开始,暂停。
public static final int PREPARE = 0; public static final int START = 1;具体代码:public static final int PAUSE = 2;
@Override public void onClick(View view) { switch (view.getId()) { case R.id.bt_start: if (timerStatus == PREPARE) { start(); bt_start.setText("暂停计时"); } else if (timerStatus == START) { pause(); bt_start.setText("继续计时"); } else if (timerStatus == PAUSE) { resume(); bt_start.setText("暂停计时"); } break; case R.id.bt_stop: stop(); break; } } private void resume() { timer = new Timer(); timer.schedule(new MyTask(), 0, 1000); timerStatus = START; } private void pause() { if (timer != null) { timer.cancel(); timerStatus = PAUSE; } } private void stop() { if (timer != null) timer.cancel(); tv_time.setText(0 + ""); bt_start.setText("开始计时"); timerStatus = PREPARE; } Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); tv_time.setText(i + ""); if (i < 0) { timer.cancel(); } } }; private void start() { String text = et_time.getText().toString(); i = Integer.parseInt(text); task = new MyTask(); timer = new Timer(); timer.schedule(task, 0, 1000); timerStatus = START; } class MyTask extends TimerTask { @Override public void run() { i--; Message msg = Message.obtain(); msg.what = 1; handler.sendMessage(msg); } }
要注意一点:
Timer 在cancel后,需要重新new 一次。
schedule和scheduleAtFixedRate的区别:(1)schedule方法:“fixed-delay”;如果第一次执行时间被delay了,随后的执行时间 按 照 上一次 实际执行完成的时间点 进行计算
(2)scheduleAtFixedRate方法:“fixed-rate”;如果第一次执行时间被delay了,随后的执行时间 按照 上一次开始的 时间点 进行计算,并且为了”catch up”会多次执行任务,TimerTask中的执行体 需要考虑同步
做了一些优化,引入了自定义控件PickerView来实现滚动选择时间,目前只是显示出来,没有加入计时器的处理,以后再来弄。
还可以优化的有:加入Service实现关闭Activity依然可以计时,实现多段暂停,记录多个时间,时间精确到ms