官方提供的用法如下:

new CountDownTimer(30000, 1000) {

     public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
} public void onFinish() {
mTextField.setText("done!");
}
}.start();

创建CountDownTimer实例之后,必须通过start()函数将计时器开启,才能保证CountDownTimer运行。CountDownTimer还提供了cancel()方法,可以将计时器取消。

在使用CountDownTimer时,必须实现两个方法:onTick() 和 onFinish()。 
在onTick(long millisUntilFinished) 中的参数millisUntilFinished是倒计时的剩余时间。在倒计时结束后会调用onFinish,倒计时结束后需要执行的操作可以写在onFinish中。

CountDownTimer(30000, 1000)中的30000,表示倒计时时间为30秒,1000表示每隔1秒钟调用一次onTick方法。

方法详解:

onTick的调用是同步的,保证这次调用不会在之前调用完成前发生。这里的同步机制主要是用来:onTick的实现需要很多时间执行比倒计时间隔更重要的事情。 
构造函数 
         public CountDownTimer (long millisInFuture, long countDownInterval) 
参数 
        millisInFuture  从开始调用start()到倒计时完成并onFinish()方法被调用的毫秒数。(倒计时时间,单位毫秒) 
        countDownInterval  接收onTick(long)回调的间隔时间。(单位毫秒) 
公共方法 
  public final void cancel () 
       取消倒计时(将会停止倒计时,5.0之前的系统不能在onTick()中调用)        
                  
  public abstract void onFinish () 
       倒计时完成时被调用

  public abstract void onTick (long millisUntilFinished) 
       固定间隔被调用 
参数 
       millisUntilFinished   倒计时剩余时间。 
  public synchronized final CountDownTimer start () 
       启动倒计时

在使用过程中发现,在一个activity或者fragment中开启了计时器,如果倒计时没有完成即退出activity或者fragment,此时onTick仍然会继续执行,当执行到mTextField.setText()时,mTextField为null,导致程序crash。因此需要在onTick中进行非空判断。

如果是在Fragment中:

if(getActivity()!=null){
//todo
}

如果是在Activity中:

if(!activity.isFinishing()){
//todo
}

但是我们不希望在fragment或activity退出之后仍然调用onTick,即使已经做了非空判断。 
我们希望在退出之后CountDownTimer也随之停止,因此在onTick中,当getActivity()==null或者activity.isFinishing()==true的时候,可以使用cancel方法取消掉计时器。

But!!! 
经过实验发现,cancel在onTick中调用,是无法成功取消计时器的。 
调用cancel之后,仍然会每隔固定时间调用onTick方法。 
然而,在5.0及以上的系统中,cancel方法就可以起到作用。对比CountDownTimer的源码发现,在5.0中,增加了一个字段

 /**
* boolean representing if the timer was cancelled
*/
private boolean mCancelled = false;

通过mCancelled 标识当前计时器是否取消。 
然后在handleMessage()中首先对mCancelled进行判断:

// handles counting down
private Handler mHandler = new Handler() { @Override
public void handleMessage(Message msg) { synchronized (CountDownTimer.this) {
if (mCancelled) { //**Attention!!!**
return;
} final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime(); if (millisLeft <= 0) {
onFinish();
} else if (millisLeft < mCountdownInterval) {
// no tick, just delay until done
sendMessageDelayed(obtainMessage(MSG), millisLeft);
} else {
long lastTickStart = SystemClock.elapsedRealtime();
onTick(millisLeft); // take into account user's onTick taking time to execute
long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime(); // special case: user's onTick took more than interval to
// complete, skip to next interval
while (delay < 0) delay += mCountdownInterval; sendMessageDelayed(obtainMessage(MSG), delay);
}
}
}
};

因此,如果想在onTick中调用cancel方法取消计时器,可以自定义一个CountDownTimerUtil,将5.0以上的CountDownTimer源码复制到CountDownTimerUtil即可。

附5.0以上系统的代码:

/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package android.os; /**
* Schedule a countdown until a time in the future, with
* regular notifications on intervals along the way.
*
* Example of showing a 30 second countdown in a text field:
*
* <pre class="prettyprint">
* new CountDownTimer(30000, 1000) {
*
* public void onTick(long millisUntilFinished) {
* mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
* }
*
* public void onFinish() {
* mTextField.setText("done!");
* }
* }.start();
* </pre>
*
* The calls to {@link #onTick(long)} are synchronized to this object so that
* one call to {@link #onTick(long)} won't ever occur before the previous
* callback is complete. This is only relevant when the implementation of
* {@link #onTick(long)} takes an amount of time to execute that is significant
* compared to the countdown interval.
*/
public abstract class CountDownTimer { /**
* Millis since epoch when alarm should stop.
*/
private final long mMillisInFuture; /**
* The interval in millis that the user receives callbacks
*/
private final long mCountdownInterval; private long mStopTimeInFuture; /**
* boolean representing if the timer was cancelled
*/
private boolean mCancelled = false; /**
* @param millisInFuture The number of millis in the future from the call
* to {@link #start()} until the countdown is done and {@link #onFinish()}
* is called.
* @param countDownInterval The interval along the way to receive
* {@link #onTick(long)} callbacks.
*/
public CountDownTimer(long millisInFuture, long countDownInterval) {
mMillisInFuture = millisInFuture;
mCountdownInterval = countDownInterval;
} /**
* Cancel the countdown.
*/
public synchronized final void cancel() {
mCancelled = true;
mHandler.removeMessages(MSG);
} /**
* Start the countdown.
*/
public synchronized final CountDownTimer start() {
mCancelled = false;
if (mMillisInFuture <= 0) {
onFinish();
return this;
}
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
mHandler.sendMessage(mHandler.obtainMessage(MSG));
return this;
} /**
* Callback fired on regular interval.
* @param millisUntilFinished The amount of time until finished.
*/
public abstract void onTick(long millisUntilFinished); /**
* Callback fired when the time is up.
*/
public abstract void onFinish(); private static final int MSG = 1; // handles counting down
private Handler mHandler = new Handler() { @Override
public void handleMessage(Message msg) { synchronized (CountDownTimer.this) {
if (mCancelled) {
return;
} final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime(); if (millisLeft <= 0) {
onFinish();
} else if (millisLeft < mCountdownInterval) {
// no tick, just delay until done
sendMessageDelayed(obtainMessage(MSG), millisLeft);
} else {
long lastTickStart = SystemClock.elapsedRealtime();
onTick(millisLeft); // take into account user's onTick taking time to execute
long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime(); // special case: user's onTick took more than interval to
// complete, skip to next interval
while (delay < 0) delay += mCountdownInterval; sendMessageDelayed(obtainMessage(MSG), delay);
}
}
}
};
}

4.4系统的代码

/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package android.os; import android.util.Log; /**
* Schedule a countdown until a time in the future, with
* regular notifications on intervals along the way.
*
* Example of showing a 30 second countdown in a text field:
*
* <pre class="prettyprint">
* new CountDownTimer(30000, 1000) {
*
* public void onTick(long millisUntilFinished) {
* mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
* }
*
* public void onFinish() {
* mTextField.setText("done!");
* }
* }.start();
* </pre>
*
* The calls to {@link #onTick(long)} are synchronized to this object so that
* one call to {@link #onTick(long)} won't ever occur before the previous
* callback is complete. This is only relevant when the implementation of
* {@link #onTick(long)} takes an amount of time to execute that is significant
* compared to the countdown interval.
*/
public abstract class CountDownTimer { /**
* Millis since epoch when alarm should stop.
*/
private final long mMillisInFuture; /**
* The interval in millis that the user receives callbacks
*/
private final long mCountdownInterval; private long mStopTimeInFuture; /**
* @param millisInFuture The number of millis in the future from the call
* to {@link #start()} until the countdown is done and {@link #onFinish()}
* is called.
* @param countDownInterval The interval along the way to receive
* {@link #onTick(long)} callbacks.
*/
public CountDownTimer(long millisInFuture, long countDownInterval) {
mMillisInFuture = millisInFuture;
mCountdownInterval = countDownInterval;
} /**
* Cancel the countdown.
*/
public final void cancel() {
mHandler.removeMessages(MSG);
} /**
* Start the countdown.
*/
public synchronized final CountDownTimer start() {
if (mMillisInFuture <= 0) {
onFinish();
return this;
}
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
mHandler.sendMessage(mHandler.obtainMessage(MSG));
return this;
} /**
* Callback fired on regular interval.
* @param millisUntilFinished The amount of time until finished.
*/
public abstract void onTick(long millisUntilFinished); /**
* Callback fired when the time is up.
*/
public abstract void onFinish(); private static final int MSG = 1; // handles counting down
private Handler mHandler = new Handler() { @Override
public void handleMessage(Message msg) { synchronized (CountDownTimer.this) {
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime(); if (millisLeft <= 0) {
onFinish();
} else if (millisLeft < mCountdownInterval) {
// no tick, just delay until done
sendMessageDelayed(obtainMessage(MSG), millisLeft);
} else {
long lastTickStart = SystemClock.elapsedRealtime();
onTick(millisLeft); // take into account user's onTick taking time to execute
long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime(); // special case: user's onTick took more than interval to
// complete, skip to next interval
while (delay < 0) delay += mCountdownInterval; sendMessageDelayed(obtainMessage(MSG), delay);
}
}
}
};
}

Android CountDownTimer的使用的更多相关文章

  1. Android CountDownTimer倒计时器的使用

    http://blog.csdn.net/freesonhp/article/details/25904047 在平时我们编程的时候,经常会用到倒计时这个功能,很多人不知道Android已经帮封装好了 ...

  2. Android CountDownTimer 类实现倒计时

    本文用 Android 中的 CountDownTimer 类实现倒计时功能,类似输入手机号获得验证码.界面如下所示: 1. 点击 “开始计时” 按钮后开始进行倒计时, 2. 倒计时过程: 3. 时间 ...

  3. Android CountDownTimer 倒计时

    摘自:http://www.cnblogs.com/over140/archive/2011/12/20/2294220.html 继承关系 public abstract class CountDo ...

  4. android CountDownTimer

    最近进行的项目使用的定时功能,我发现了一个非常容易使用内置类CountDownTimer.当然,可以使用这种效果TimerTask + Timer为了实现.只是我个人的意见CountDownTimer ...

  5. Android使用CountDownTimer倒计时

    1.布局文件 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android ...

  6. 拓展 Android 原生 CountDownTimer 倒计时

    拓展 Android 原生 CountDownTimer 倒计时 [TOC] CountDownTimer 在系统的CountDownTimer上进行的修改,主要是拓展了功能,当然也保留了系统默认的模 ...

  7. [Android Pro] CountDownTimer倒计时

    定时执行在一段时候后停止的倒计时,在倒计时执行过程中会在固定间隔时间得到通知(译者:触发onTick方法),下面的例子显示在一个文本框中显示一个30s倒计时: new CountdownTimer(3 ...

  8. Android基础之CountDownTimer 倒计时类

    app常用的60s倒计时计时功能: private static final int TIME_LIMIT = 60; private void initView() { // 相关控件 mResen ...

  9. Android中使用Handler以及CountDownTimer实现包含倒计时的闪屏页面

    上一篇博文<Android中Handler使用浅析>通过实现倒计时闪屏页面的制作引出了Handler的使用方法以及实现原理,博文末尾也提到了实现过程中的Bug,有兴趣的朋友可以点击链接回去 ...

随机推荐

  1. 数据分片存储,mycat服务器

    关闭防火墙和selinux,配置yum源配置21 .22 数据库(这里以21为例)[root@host21 ~]# tar -xf mysql-5.7.17.tar[root@host21 ~]# y ...

  2. node遍历给定目录下特定文件,内容合并到一个文件

    遍历目录用了fs.readdir这个异步方法,得到当前目录下所有的文件和目录的一个数组.然后判断: if文件,并且后缀符合设定的规则(本文例子是符合后缀ts,js)直接用同步方法写入, if目录,继续 ...

  3. mac install telnet

    问题: -bash: telnet: command not found -bash: brew: command not found 解决: /usr/bin/ruby -e "$(cur ...

  4. java面试题链接

    http://blog.csdn.net/jackfrued/article/details/17339393

  5. 洛谷——P4296 [AHOI2007]密码箱

    P4296 [AHOI2007]密码箱 密码x大于等于0,且小于n,而x的平方除以n,得到的余数为1. 求这个密码,$1<=n<=2,000,000,000$ 暴力枚举,数据有点儿水$O( ...

  6. 洛谷——P1156 垃圾陷阱

    P1156 垃圾陷阱 题目描述 卡门――农夫约翰极其珍视的一条Holsteins奶牛――已经落了到“垃圾井”中.“垃圾井”是农夫们扔垃圾的地方,它的深度为D(2 \le D \le 100)D(2≤D ...

  7. java中通用权限管理设计(转)

    原文地址:http://www.cnblogs.com/a7345678/archive/2008/09/25/1298838.html 转自博客园暗夜精灵-鬼才阁 实现业务系统中的用户权限管理 B/ ...

  8. CentOS 6磁盘配额

    可以指定用户能超过其配额限制.如果不想拒绝用户对卷的访问但想跟踪每个用户的磁盘空间使用情况,启用配额而且不限制磁盘空间的使用是非常有用的.也可指定不管用户超过配额警告级别还是超过配额限制时是否要记录事 ...

  9. CentOS 6 Yum本地源配置

    #cd /etc/yum.repos.d #rm CentOS-Base.repo CentOS-Base.repo 是yum 网络源的配置文件(默认) #vi CentOS-Media.repo C ...

  10. vue-cli 3.x 配置多环境

    思路:新建一个 process.env 变量. 把 webpack 配置放到 vue.config.js 里面. 如果根目录下没有该文件,新建.配置参考:https://cli.vuejs.org/z ...