欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android计时器和倒计时

程序员文章站 2022-04-04 16:47:02
...

1. 计时器

两个核心类 Timer 和 TimerTask

 

1) Timer核心方法

 

//Schedules the specified task for execution after the specified delay.
void schedule(TimerTask task, long delay)

//Schedules the specified task for repeated fixed-delay execution, beginning after the specified delay.
void schedule(TimerTask task, long delay, long period)

 

 

第一个方法只执行一次;

第二个方式每隔period执行一次,delay表示每次执行的延时时间,其实主要表现在第一次的延时效果,比如delay设置为0,那么立马执行task内容,如果设置为1000,那么第一次执行task会有一秒的延时效果。

 

2) TimerTask用于继承(或者直接定义并初始化匿名类),并重写run方法,定义自己的业务逻辑。

 

3) 手动结束定时器,

Timer和TimerTask都有cancel方法,而且最好同时调用

如果已经cancel,下次必须创建新的Timer才能schedule

 

4) 如果你在当前的activity中schedule了一个task,但是没有等到task结束,就按Back键finish了当前的activity,Timer和TimerTask并不会自动cancel或者销毁,它还会在后台运行,此时如果你在task的某个阶段要调起一个控件(比如AlertDialog),而该控制依赖被销毁的activity,那么将会引发crash。

 

5) 例如对进度条实现每一秒递增的效果(主要代码)

//总时长
private static final long TOTAL_QUERY_MINUTES = 50;
//比如每5秒去查询数据库
private static final long QUERY_INTERVAL = 5 *1000;

private static final int TIMER_SCHEDULE_CODE = 1;

int timePassed=0;

QueryTimerTask queryTask;

private Timer timer;

//显示定时器的效果
ProgressBar statusBar;

private Handler mHandler= new Handler(new Handler.Callback() {

    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            
            case TIMER_SCHEDULE_CODE:
                statusBar.setProgress(timePassed);

                //Log.w(TAG, "timePassed : " + timePassed + " -- TOTAL_QUERY_MINUTES : " + TOTAL_QUERY_MINUTES);
                if (timePassed>=TOTAL_QUERY_MINUTES){
                    if (timer != null)
                        timer.cancel();

                    if (queryTask != null)
                        queryTask.cancel();


                    new AlertDialog.Builder(YourActivity.this).
                            setTitle("超时通知").setMessage("已超时,是否继续等待?")
                        .setPositiveButton("继续等待", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                reSchedule();
                            }
                        })
                        .setNegativeButton("取消任务", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                //cancelTask();
                            }
                        }).show();
                
                break;
            
            //....
        }

        return true;
    }
});

void reSchedule() {
    timePassed = 0;

    if (timer != null) {
        timer.cancel();
    }

    if (queryTask != null) {
        queryTask.cancel();
    }

    timer = new Timer();
    queryTask = new QueryTimerTask();
    //每一秒执行一次,第一次有延时一秒的效果
    timer.schedule(queryTask, 1000, 1000);
}

//自定义task
class QueryTimerTask extends TimerTask {
    @Override
    public void run() {

    	//比如每过QUERY_INTERVAL去查询信息
        if ((timePassed * 1000) % QUERY_INTERVAL == 0) {
            //query();
        }

        timePassed++;

        //通知handler去改变statusBar
        Message message = mHandler.obtainMessage();
        message.what = TIMER_SCHEDULE_CODE;
        mHandler.sendMessage(message);
    }
}

 

 2. 倒计时

其实也可以用上面的方法实现,

安卓额外提供了CountdownTimer类

 

//由于以1秒间隔不准,所以取其一半来做间隔
int countTemp = 2;

//此处写的是500的间隔,实际通过countTemp达到1秒间隔的效果
countDownTimer = new CountDownTimer(5000, 500) {
        @Override
        public void onTick(long millisUntilFinished) {
            if (countTemp == 2) {
                //可以看出来其实millis并不是非常标准的
                Log.w(TAG, String.format("%d秒", millisUntilFinished));
                Log.w(TAG, String.format("%d秒", Math.round(millisUntilFinished / 1000.0)));
                getCodeBtn.setText(String.format("%d秒", Math.round(millisUntilFinished / 1000.0)));

                countTemp--;
            } else {
                countTemp++;
            }
        }

        @Override
        public void onFinish() {
            getCodeBtn.setText("获取验证码");
            isCountDown = true;
            countTemp = 2;
        }
    };
}

//开始倒计时
countDownTimer.start();

 

这个类实际使用还是有点麻烦的,详见

Android: CountDownTimer skips last onTick

Android CountDownTimer shows 1 for two seconds

CountDownTimer skipping one second when displaying on TextView